added webhooks and templates to alerting, email is next
This commit is contained in:
@@ -2195,6 +2195,9 @@ Create a new webhook configuration.
|
||||
| `severity_filter` | array | No | Array of severities to filter (empty = all severities) |
|
||||
| `timeout` | integer | No | Request timeout in seconds (default: 10) |
|
||||
| `retry_count` | integer | No | Number of retry attempts (default: 3) |
|
||||
| `template` | string | No | Jinja2 template for custom payload (leave empty for default format) |
|
||||
| `template_format` | string | No | Template output format: json, text (default: json) |
|
||||
| `content_type_override` | string | No | Custom Content-Type header (auto-detected if not specified) |
|
||||
|
||||
**Success Response (201 Created):**
|
||||
```json
|
||||
@@ -2258,6 +2261,19 @@ curl -X POST http://localhost:5000/api/webhooks \
|
||||
"auth_token": "your-secret-token"
|
||||
}' \
|
||||
-b cookies.txt
|
||||
|
||||
# Create webhook with custom template
|
||||
curl -X POST http://localhost:5000/api/webhooks \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"name": "Gotify Notifications",
|
||||
"url": "https://gotify.example.com/message",
|
||||
"template": "{\"title\": \"{{ scan.title }}\", \"message\": \"{{ alert.message }}\", \"priority\": {% if alert.severity == \"critical\" %}5{% else %}3{% endif %}}",
|
||||
"template_format": "json",
|
||||
"auth_type": "custom",
|
||||
"custom_headers": {"X-Gotify-Key": "your-app-token"}
|
||||
}' \
|
||||
-b cookies.txt
|
||||
```
|
||||
|
||||
### Update Webhook
|
||||
@@ -2421,6 +2437,126 @@ curl -X POST http://localhost:5000/api/webhooks/1/test \
|
||||
-b cookies.txt
|
||||
```
|
||||
|
||||
### Preview Template
|
||||
|
||||
Preview a webhook template with sample data before saving.
|
||||
|
||||
**Endpoint:** `POST /api/webhooks/preview-template`
|
||||
|
||||
**Authentication:** Required
|
||||
|
||||
**Request Body:**
|
||||
```json
|
||||
{
|
||||
"template": "{\"title\": \"{{ scan.title }}\", \"message\": \"{{ alert.message }}\"}",
|
||||
"template_format": "json"
|
||||
}
|
||||
```
|
||||
|
||||
**Request Body Fields:**
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| `template` | string | Yes | Jinja2 template to preview |
|
||||
| `template_format` | string | No | Output format: json or text (default: json) |
|
||||
|
||||
**Success Response (200 OK):**
|
||||
```json
|
||||
{
|
||||
"status": "success",
|
||||
"rendered": "{\"title\": \"Production Infrastructure Scan\", \"message\": \"Unexpected port 8080 found open on 192.168.1.100\"}",
|
||||
"format": "json"
|
||||
}
|
||||
```
|
||||
|
||||
**Error Responses:**
|
||||
|
||||
*400 Bad Request* - Template validation error:
|
||||
```json
|
||||
{
|
||||
"status": "error",
|
||||
"message": "Template validation error: Unexpected '}}' at line 2"
|
||||
}
|
||||
```
|
||||
|
||||
*400 Bad Request* - Template rendering error:
|
||||
```json
|
||||
{
|
||||
"status": "error",
|
||||
"message": "Template rendering error: undefined variable 'invalid_var'"
|
||||
}
|
||||
```
|
||||
|
||||
**Usage Example:**
|
||||
```bash
|
||||
curl -X POST http://localhost:5000/api/webhooks/preview-template \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"template": "{\"title\": \"Alert\", \"message\": \"{{ alert.message }}\"}",
|
||||
"template_format": "json"
|
||||
}' \
|
||||
-b cookies.txt
|
||||
```
|
||||
|
||||
### Get Template Presets
|
||||
|
||||
Get list of available webhook template presets for popular services.
|
||||
|
||||
**Endpoint:** `GET /api/webhooks/template-presets`
|
||||
|
||||
**Authentication:** Required
|
||||
|
||||
**Success Response (200 OK):**
|
||||
```json
|
||||
{
|
||||
"status": "success",
|
||||
"presets": [
|
||||
{
|
||||
"id": "default_json",
|
||||
"name": "Default JSON (Current Format)",
|
||||
"description": "Standard webhook payload format matching the current implementation",
|
||||
"format": "json",
|
||||
"content_type": "application/json",
|
||||
"category": "general",
|
||||
"template": "{\n \"event\": \"alert.created\",\n \"alert\": {...}\n}"
|
||||
},
|
||||
{
|
||||
"id": "gotify",
|
||||
"name": "Gotify",
|
||||
"description": "Optimized for Gotify push notification server with markdown support",
|
||||
"format": "json",
|
||||
"content_type": "application/json",
|
||||
"category": "service",
|
||||
"template": "{\n \"title\": \"{{ scan.title }}\",\n \"message\": \"{{ alert.message }}\",\n \"priority\": {% if alert.severity == 'critical' %}8{% else %}5{% endif %}\n}"
|
||||
},
|
||||
{
|
||||
"id": "slack",
|
||||
"name": "Slack",
|
||||
"description": "Rich Block Kit format for Slack webhooks with visual formatting",
|
||||
"format": "json",
|
||||
"content_type": "application/json",
|
||||
"category": "service",
|
||||
"template": "..."
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Available Presets:**
|
||||
- `default_json` - Standard JSON format (backward compatible)
|
||||
- `custom_json` - Flexible custom format with title/message/priority
|
||||
- `gotify` - Gotify push notification server format
|
||||
- `ntfy` - Simple text format for Ntfy pub-sub service
|
||||
- `slack` - Slack Block Kit format with rich formatting
|
||||
- `discord` - Discord embedded message format
|
||||
- `plain_text` - Simple plain text format
|
||||
|
||||
**Usage Example:**
|
||||
```bash
|
||||
curl -X GET http://localhost:5000/api/webhooks/template-presets \
|
||||
-b cookies.txt
|
||||
```
|
||||
|
||||
### Get Webhook Delivery Logs
|
||||
|
||||
Get delivery history for a specific webhook.
|
||||
@@ -2508,7 +2644,9 @@ curl -X GET "http://localhost:5000/api/webhooks/1/logs?page=2" \
|
||||
|
||||
### Webhook Payload Format
|
||||
|
||||
When alerts are triggered, webhooks receive JSON payloads in this format:
|
||||
#### Default Format
|
||||
|
||||
When alerts are triggered, webhooks without custom templates receive JSON payloads in this default format:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -2538,6 +2676,76 @@ When alerts are triggered, webhooks receive JSON payloads in this format:
|
||||
}
|
||||
```
|
||||
|
||||
#### Custom Templates
|
||||
|
||||
Webhooks support custom Jinja2 templates to customize the payload format for different services. Templates have access to the following variables:
|
||||
|
||||
**Available Template Variables:**
|
||||
|
||||
| Variable | Description | Example |
|
||||
|----------|-------------|---------|
|
||||
| `{{ alert.id }}` | Alert ID | `123` |
|
||||
| `{{ alert.type }}` | Alert type | `"cert_expiry"`, `"unexpected_port"` |
|
||||
| `{{ alert.severity }}` | Severity level | `"critical"`, `"warning"`, `"info"` |
|
||||
| `{{ alert.message }}` | Human-readable message | `"Certificate expires in 15 days"` |
|
||||
| `{{ alert.ip_address }}` | IP address | `"192.168.1.10"` |
|
||||
| `{{ alert.port }}` | Port number | `443` |
|
||||
| `{{ alert.acknowledged }}` | Is acknowledged | `true`, `false` |
|
||||
| `{{ alert.created_at }}` | Creation timestamp | `datetime` object |
|
||||
| `{{ scan.id }}` | Scan ID | `42` |
|
||||
| `{{ scan.title }}` | Scan title | `"Production Network Scan"` |
|
||||
| `{{ scan.status }}` | Scan status | `"completed"`, `"running"`, `"failed"` |
|
||||
| `{{ scan.duration }}` | Scan duration (seconds) | `125.5` |
|
||||
| `{{ scan.triggered_by }}` | How scan was triggered | `"manual"`, `"scheduled"`, `"api"` |
|
||||
| `{{ rule.id }}` | Rule ID | `3` |
|
||||
| `{{ rule.name }}` | Rule name | `"Certificate Expiry Warning"` |
|
||||
| `{{ rule.type }}` | Rule type | `"cert_expiry"` |
|
||||
| `{{ rule.threshold }}` | Rule threshold | `30` |
|
||||
| `{{ app.name }}` | Application name | `"SneakyScanner"` |
|
||||
| `{{ app.version }}` | Application version | `"1.0.0-phase5"` |
|
||||
| `{{ app.url }}` | Repository URL | `"https://github..."` |
|
||||
| `{{ timestamp }}` | Current UTC timestamp | `datetime` object |
|
||||
|
||||
**Jinja2 Features:**
|
||||
- Conditionals: `{% if alert.severity == 'critical' %}...{% endif %}`
|
||||
- Filters: `{{ alert.type|upper }}`, `{{ alert.created_at.isoformat() }}`
|
||||
- Default values: `{{ alert.port|default('N/A') }}`
|
||||
|
||||
**Template Examples:**
|
||||
|
||||
*Custom JSON with priority:*
|
||||
```jinja2
|
||||
{
|
||||
"title": "{{ scan.title }}",
|
||||
"message": "{{ alert.message }}",
|
||||
"priority": {% if alert.severity == 'critical' %}5{% elif alert.severity == 'warning' %}3{% else %}1{% endif %},
|
||||
"alert_id": {{ alert.id }}
|
||||
}
|
||||
```
|
||||
|
||||
*Plain text format:*
|
||||
```jinja2
|
||||
ALERT: {{ alert.severity|upper }}
|
||||
{{ alert.message }}
|
||||
|
||||
Scan: {{ scan.title }}
|
||||
Rule: {{ rule.name }}
|
||||
Time: {{ timestamp.strftime('%Y-%m-%d %H:%M:%S UTC') }}
|
||||
```
|
||||
|
||||
*Gotify format:*
|
||||
```jinja2
|
||||
{
|
||||
"title": "{{ scan.title }}",
|
||||
"message": "**{{ alert.severity|upper }}**: {{ alert.message }}",
|
||||
"priority": {% if alert.severity == 'critical' %}8{% elif alert.severity == 'warning' %}5{% else %}2{% endif %},
|
||||
"extras": {
|
||||
"client::display": {"contentType": "text/markdown"},
|
||||
"alert_id": {{ alert.id }}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Authentication Types
|
||||
|
||||
**None:**
|
||||
@@ -2840,8 +3048,8 @@ API versioning will be implemented in future phases. For now, the API is conside
|
||||
- **Webhooks API** - Webhook management, delivery tracking, authentication support, retry logic
|
||||
|
||||
### Endpoint Count
|
||||
- Total endpoints: 65+
|
||||
- Authenticated endpoints: 60+
|
||||
- Total endpoints: 67+
|
||||
- Authenticated endpoints: 62+
|
||||
- Public endpoints: 5 (login, setup, health checks)
|
||||
|
||||
---
|
||||
@@ -2855,5 +3063,5 @@ For issues, questions, or feature requests:
|
||||
---
|
||||
|
||||
**Last Updated:** 2025-11-18
|
||||
**Phase:** 5 - Alerts Management
|
||||
**Phase:** 5 - Alerts Management & Custom Webhook Templates
|
||||
**Next Update:** Phase 6 - Future Enhancements
|
||||
|
||||
Reference in New Issue
Block a user