Files
pulse/docs/WEBHOOKS.md
T
rcourtman 9496d6f6d8 Fix four customer-facing doc drift findings (RBAC, OIDC, helm, webhooks)
RBAC.md (alerts:read → monitoring:read):
The example team-setup table told operators to issue API tokens with an
"alerts:read" scope. That scope does not exist in pkg/auth/scopes.go;
defined scopes are monitoring:read, settings:read, etc. /api/alerts/ is
gated by RequireAuth (no specific scope required), so an integrator
issuing a token would naturally pick the closest real scope —
monitoring:read — and that is what the doc should have shown.

OIDC.md (OIDC_GROUP_ROLE_MAPPINGS, OIDC_CA_BUNDLE):
Both env vars were documented but zero code reads them. OIDC config is
per-provider in internal/config/sso.go and OIDCProviderConfig in
internal/config/oidc.go: groupRoleMappings is a map field; caBundle is a
path field. Replace both env-var snippets with the actual UI/API path so
operators following the secure-install flow don't silently get no group
mapping or no custom CA trust. Same drift pattern as the earlier rc.1 →
rc.5 PULSE_RELAY_* aspiration-without-implementation.

WEBHOOKS.md (missing helpers):
notifications.go's templateFuncMap registers jsonString and pathescape
on every webhook template, but the helper list only documented title /
upper / lower / printf / urlquery / urlencode / urlpath. Add both, with
a short note that jsonString is the safe way to embed arbitrary string
values inside a JSON payload — Pulse's shipped templates use it
everywhere a value goes inside JSON, and operators writing custom
templates were missing the canonical escape primitive.

KUBERNETES.md (helm path + markdown fence):
- "deployment.strategy.type=Recreate" was the wrong helm path. The
  chart's strategy block is at the top level (deploy/helm/pulse/values.yaml
  line 9), so `strategy.type=Recreate` is what operators must actually
  --set. Following the broken path produced no override and left RWO
  PVC deployments on the default RollingUpdate, the exact Multi-Attach
  failure mode the note was trying to warn against.
- Trailing ```text on the helm-template code block closed the fence
  but tagged it as a language, breaking markdown rendering in some
  readers. Reduced to plain ```.

All four are doc-only changes; no code reads the names they document.
2026-05-12 15:54:24 +01:00

77 lines
3.6 KiB
Markdown

# 🔔 Webhooks
Pulse includes built-in templates for popular services and a generic JSON template for custom endpoints.
## 🚀 Quick Setup
1. Go to **Alerts → Notification Destinations**.
2. Click **Add Webhook**.
3. Select service type and paste the URL.
## 📝 Service URLs
| Service | URL Format |
|---------|------------|
| **Discord** | `https://discord.com/api/webhooks/{id}/{token}` |
| **Slack** | `https://hooks.slack.com/services/...` |
| **Teams** | `https://{tenant}.webhook.office.com/webhookb2/{webhook_path}` |
| **Teams (Adaptive Card)** | `https://{tenant}.webhook.office.com/webhookb2/{webhook_path}` |
| **Telegram** | `https://api.telegram.org/bot{bot_token}/sendMessage?chat_id={chat_id}` |
| **PagerDuty** | `https://events.pagerduty.com/v2/enqueue` |
| **Pushover** | `https://api.pushover.net/1/messages.json` |
| **Gotify** | `https://gotify.example.com/message?token={token}` |
| **ntfy** | `https://ntfy.sh/{topic}` |
| **Generic** | `https://example.com/webhook` |
## 🎨 Custom Templates
For generic webhooks, use Go templates to format the JSON payload.
**Variables (common):**
- `{{.ID}}`, `{{.Level}}`, `{{.Type}}`
- `{{.ResourceName}}`, `{{.ResourceID}}`, `{{.ResourceType}}`, `{{.Node}}`
- `{{.Message}}`, `{{.Value}}`, `{{.Threshold}}`, `{{.Duration}}`, `{{.Timestamp}}`
- `{{.Instance}}` (Pulse public URL if configured)
- `{{.CustomFields.<name>}}` (user-defined fields in the UI)
- `{{.Metadata}}` (alert metadata map)
- `{{.AlertCount}}`, `{{.Alerts}}` (grouped alerts)
- `{{.Mention}}` (platform-specific mention, if configured)
**Convenience fields:**
- `{{.ValueFormatted}}`, `{{.ThresholdFormatted}}`
- `{{.StartTime}}`, `{{.Acknowledged}}`, `{{.AckTime}}`, `{{.AckUser}}`
**Template helpers:** `title`, `upper`, `lower`, `printf`, `urlquery`/`urlencode`, `urlpath`/`pathescape`, `jsonString`
`jsonString` is the safe way to embed string values inside a JSON payload — it escapes quotes, backslashes, and control characters without wrapping the value in surrounding quotes, so you can write `"text": "{{.Message | jsonString}}"` and stay valid JSON even when the message contains `"` or newlines. Pulse's shipped templates use it extensively; prefer it over manual escaping in custom templates.
**Service-specific notes:**
- **Telegram**: include `chat_id` in the URL query string.
- **Telegram templates**: `{{.ChatID}}` is populated from the URL query string.
- **PagerDuty**: set `routing_key` as a custom field (or header) in the webhook config.
- **Pushover**: add `token` and `user` custom fields (required). Legacy `app_token` and `user_token` inputs are migrated automatically.
**Example Payload:**
```json
{
"text": "Alert: {{.Level}} - {{.Message}}",
"value": {{.Value}}
}
```
## 🛡️ Security
- **Private IPs**: By default, webhooks to private IPs are blocked. Allow them in **Settings → System → Network → Webhook Security**.
- **Headers**: Add custom headers (e.g., `Authorization: Bearer ...`) in the webhook config.
## 🧾 Audit Webhooks (Pro/legacy Pro+/Cloud)
Pro, legacy Pro+, and Cloud support dedicated audit webhooks for security event compliance. Unlike alert notifications, these webhooks deliver the raw, signed JSON payload of every security-relevant action (login, config change, group mapping).
### Setup
1. Go to **Settings → Security → Webhooks**.
2. Add your endpoint URL (e.g., `https://siem.corp.local/ingest/pulse`).
### Security
Audit webhooks are dispatched asynchronously. The payload includes a `signature` field which can be verified using the per-instance HMAC key stored (encrypted) at `.audit-signing.key` in the Pulse data directory. There is no `PULSE_AUDIT_SIGNING_KEY` override.