Documentation
¶
Overview ¶
Package alerts implements the cert-expiry alerter: a periodic scanner that detects host certificates approaching their expiry without having been auto-renewed and fans the event out to one or more sinks (audit log, webhook, Prometheus gauge).
State lives in the cert_alerts table — one row per host — so a given (host, not_after) pair fires at most once even if the scan tick fires many times before someone rotates the cert.
Index ¶
Constants ¶
const AuditActionCertExpiring = "cert.expiring"
Audit action emitted by the cert-expiry alerter. Kept here as a constant so receivers (parsers, dashboards) can match against a stable identifier.
const SignatureHeader = "X-Nebula-Signature"
SignatureHeader is the HTTP header webhook receivers should inspect to authenticate the request body. Exported for documentation tests.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Alert ¶
type Alert struct {
HostID string
HostName string
NetworkID string
CAID string
Fingerprint string
NotAfter time.Time
SecondsUntilExpiry float64
}
Alert is the structured event a Sink receives.
type AuditSink ¶
AuditSink writes each Alert to the store's audit log as a structured `cert.expiring` entry. Always-on by design: the audit log is the no-config-required fallback documented in the issue.
type Scanner ¶
type Scanner struct {
Store store.Store
Threshold time.Duration
Interval time.Duration
Sinks []Sink
Logger *slog.Logger
}
Scanner is a periodic cert-expiry watchdog. Wire one up at server start, call StartLoop with a cancellable context, and it ticks every Interval until the context is canceled.
func (*Scanner) Run ¶
Run performs a single sweep: enumerate enrolled hosts' current certs, filter to those whose remaining lifetime is shorter than Threshold, and emit one Alert per (host, not_after) pair that has not yet been alerted.
Errors from individual sinks are logged but do not stop the loop; the dedup record is still written so retries happen at the next threshold crossing (cert rotation) rather than every tick.
type Sink ¶
Sink is the interface implemented by alert delivery backends — audit log, webhook, Prometheus gauge, etc. A sink's Notify call is expected to be fast and best-effort; the scanner records the alert as fired regardless of individual sink failures so a flaky webhook does not block the audit log entry or trigger duplicate delivery on the next scan tick.
type WebhookSink ¶
type WebhookSink struct {
URL string
HMACSecret string
HTTPClient *http.Client
// AllowPrivate disables the request-time private-address guard,
// mirroring alerts.allow_private_webhook for intentional internal
// sinks. Only consulted when HTTPClient is nil — a caller-supplied
// client manages its own transport policy.
AllowPrivate bool
}
WebhookSink POSTs every alert as JSON to URL with an HMAC-SHA256 signature in the X-Nebula-Signature header (sha256=<hex>). If HMACSecret is empty, the signature header is omitted — useful for trusted-internal alertmanager endpoints behind mTLS where signing is redundant.
Unless AllowPrivate is set, deliveries are SSRF-guarded at request time: the dialer rejects connections to private/loopback/link-local addresses after DNS resolution, and redirects re-apply the same check per hop. This complements the config-load check in validateWebhookURL, which cannot see what a hostname resolves to at delivery time or where a redirect points.