choret: enforce discord-only provider type across notifications API and UI
- Added validation to reject non-discord provider types in create, update, test, and preview operations. - Updated the notifications form to automatically normalize non-discord types to discord. - Modified UI to display explicit messaging for deprecated and non-dispatch statuses for non-discord providers. - Enhanced tests to cover new validation logic and UI changes for provider types.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# Notification System
|
||||
|
||||
Charon's notification system keeps you informed about important events in your infrastructure through multiple channels, including Discord, Slack, Gotify, Telegram, and custom webhooks.
|
||||
Charon's notification system keeps you informed about important events in your infrastructure. With flexible JSON templates and support for multiple providers, you can customize how and where you receive alerts.
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -11,15 +11,13 @@ Notifications can be triggered by various events:
|
||||
- **Security Events**: WAF blocks, CrowdSec alerts, ACL violations
|
||||
- **System Events**: Configuration changes, backup completions
|
||||
|
||||
## Supported Services
|
||||
## Supported Service (Current Rollout)
|
||||
|
||||
| Service | JSON Templates | Native API | Rich Formatting |
|
||||
|---------|----------------|------------|-----------------|
|
||||
| **Discord** | ✅ Yes | ✅ Webhooks | ✅ Embeds |
|
||||
| **Slack** | ✅ Yes | ✅ Incoming Webhooks | ✅ Block Kit |
|
||||
| **Gotify** | ✅ Yes | ✅ REST API | ✅ Extras |
|
||||
| **Generic Webhook** | ✅ Yes | ✅ HTTP POST | ✅ Custom |
|
||||
| **Telegram** | ❌ No | ✅ Bot API | ⚠️ Markdown |
|
||||
|
||||
Additional providers are planned for later staged releases.
|
||||
|
||||
### Why JSON Templates?
|
||||
|
||||
@@ -43,7 +41,7 @@ JSON templates give you complete control over notification formatting, allowing
|
||||
|
||||
### JSON Template Support
|
||||
|
||||
For services supporting JSON (Discord, Slack, Gotify, Generic, Webhook), you can choose from three template options:
|
||||
For the currently supported service (Discord), you can choose from three template options:
|
||||
|
||||
#### 1. Minimal Template (Default)
|
||||
|
||||
@@ -157,167 +155,11 @@ Discord supports rich embeds with colors, fields, and timestamps.
|
||||
- `16776960` - Yellow (warning)
|
||||
- `3066993` - Green (success)
|
||||
|
||||
### Slack Webhooks
|
||||
## Planned Provider Expansion
|
||||
|
||||
Slack uses Block Kit for rich message formatting.
|
||||
|
||||
#### Basic Block
|
||||
|
||||
```json
|
||||
{
|
||||
"text": "{{.Title}}",
|
||||
"blocks": [
|
||||
{
|
||||
"type": "header",
|
||||
"text": {
|
||||
"type": "plain_text",
|
||||
"text": "{{.Title}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "section",
|
||||
"text": {
|
||||
"type": "mrkdwn",
|
||||
"text": "{{.Message}}"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
#### Advanced Block with Context
|
||||
|
||||
```json
|
||||
{
|
||||
"text": "{{.Title}}",
|
||||
"blocks": [
|
||||
{
|
||||
"type": "header",
|
||||
"text": {
|
||||
"type": "plain_text",
|
||||
"text": "🔔 {{.Title}}",
|
||||
"emoji": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "section",
|
||||
"text": {
|
||||
"type": "mrkdwn",
|
||||
"text": "*Event:* {{.EventType}}\n*Message:* {{.Message}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "section",
|
||||
"fields": [
|
||||
{
|
||||
"type": "mrkdwn",
|
||||
"text": "*Host:*\n{{.HostName}}"
|
||||
},
|
||||
{
|
||||
"type": "mrkdwn",
|
||||
"text": "*Time:*\n{{.Timestamp}}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "context",
|
||||
"elements": [
|
||||
{
|
||||
"type": "mrkdwn",
|
||||
"text": "Notification from Charon"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Slack Markdown Tips:**
|
||||
|
||||
- `*bold*` for emphasis
|
||||
- `_italic_` for subtle text
|
||||
- `~strike~` for deprecated info
|
||||
- `` `code` `` for technical details
|
||||
- Use `\n` for line breaks
|
||||
|
||||
### Gotify Webhooks
|
||||
|
||||
Gotify supports JSON payloads with priority levels and extras.
|
||||
|
||||
#### Basic Message
|
||||
|
||||
```json
|
||||
{
|
||||
"title": "{{.Title}}",
|
||||
"message": "{{.Message}}",
|
||||
"priority": 5
|
||||
}
|
||||
```
|
||||
|
||||
#### Advanced Message with Extras
|
||||
|
||||
```json
|
||||
{
|
||||
"title": "{{.Title}}",
|
||||
"message": "{{.Message}}",
|
||||
"priority": {{.Priority}},
|
||||
"extras": {
|
||||
"client::display": {
|
||||
"contentType": "text/markdown"
|
||||
},
|
||||
"client::notification": {
|
||||
"click": {
|
||||
"url": "https://your-charon-instance.com"
|
||||
}
|
||||
},
|
||||
"charon": {
|
||||
"event_type": "{{.EventType}}",
|
||||
"host_name": "{{.HostName}}",
|
||||
"timestamp": "{{.Timestamp}}"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Gotify Priority Levels:**
|
||||
|
||||
- `0` - Very low
|
||||
- `2` - Low
|
||||
- `5` - Normal (default)
|
||||
- `8` - High
|
||||
- `10` - Very high (emergency)
|
||||
|
||||
#### Gotify Token Hygiene (Required)
|
||||
|
||||
- Never echo, log, or return Gotify token values.
|
||||
- Never expose tokenized endpoint query strings (for example,
|
||||
`...?token=...`) in logs, diagnostics, examples, screenshots,
|
||||
tickets, or reports.
|
||||
- Redact or mask query parameters in diagnostics and examples before sharing.
|
||||
- Use write-only token inputs in operator workflows.
|
||||
- Store tokens in environment variables or a secret manager, not plaintext notes.
|
||||
- Validate endpoint connectivity over HTTPS only.
|
||||
- Rotate tokens immediately on suspected exposure.
|
||||
|
||||
### Generic Webhooks
|
||||
|
||||
For custom integrations, use any JSON structure:
|
||||
|
||||
```json
|
||||
{
|
||||
"notification": {
|
||||
"type": "{{.EventType}}",
|
||||
"level": "{{.Severity}}",
|
||||
"title": "{{.Title}}",
|
||||
"body": "{{.Message}}",
|
||||
"metadata": {
|
||||
"host": "{{.HostName}}",
|
||||
"timestamp": "{{.Timestamp}}",
|
||||
"source": "charon"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
Additional providers (for example Slack, Gotify, Telegram, and generic webhooks)
|
||||
are planned for later staged releases. This page will be expanded as each
|
||||
provider is validated and released.
|
||||
|
||||
## Template Variables
|
||||
|
||||
@@ -386,12 +228,16 @@ Template: detailed (or custom)
|
||||
4. Test the notification
|
||||
5. Save changes
|
||||
|
||||
If you previously used non-Discord provider types, keep those entries as
|
||||
historical records only. They are not active runtime dispatch paths in the
|
||||
current rollout.
|
||||
|
||||
### Testing Your Template
|
||||
|
||||
Before saving, always test your template:
|
||||
|
||||
1. Click **"Send Test Notification"** in the provider form
|
||||
2. Check your notification channel (Discord/Slack/etc.)
|
||||
2. Check your Discord channel
|
||||
3. Verify formatting, colors, and all fields appear correctly
|
||||
4. Adjust template if needed
|
||||
5. Test again until satisfied
|
||||
@@ -419,7 +265,7 @@ Before saving, always test your template:
|
||||
1. ✅ Provider is enabled
|
||||
2. ✅ Event type is configured for notifications
|
||||
3. ✅ Webhook URL is correct
|
||||
4. ✅ Service (Discord/Slack/etc.) is online
|
||||
4. ✅ Discord is online
|
||||
5. ✅ Test notification succeeds
|
||||
6. ✅ Check Charon logs for errors: `docker logs charon | grep notification`
|
||||
|
||||
@@ -440,26 +286,6 @@ Before saving, always test your template:
|
||||
}
|
||||
```
|
||||
|
||||
### Slack Message Appears Plain
|
||||
|
||||
**Cause:** Block Kit requires specific formatting.
|
||||
|
||||
**Solution:** Use `blocks` array with proper types:
|
||||
|
||||
```json
|
||||
{
|
||||
"blocks": [
|
||||
{
|
||||
"type": "section",
|
||||
"text": {
|
||||
"type": "mrkdwn",
|
||||
"text": "{{.Message}}"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### 1. Start Simple
|
||||
@@ -481,19 +307,17 @@ Consistent colors help quickly identify severity:
|
||||
|
||||
### 4. Group Related Events
|
||||
|
||||
Configure multiple providers for different event types:
|
||||
Use separate Discord providers for different event types:
|
||||
|
||||
- Critical alerts → Discord (with mentions)
|
||||
- Info notifications → Slack (general channel)
|
||||
- All events → Gotify (personal alerts)
|
||||
- Info notifications → Discord (general channel)
|
||||
- Security events → Discord (security channel)
|
||||
|
||||
### 5. Rate Limit Awareness
|
||||
|
||||
Be mindful of service limits:
|
||||
|
||||
- **Discord**: 5 requests per 2 seconds per webhook
|
||||
- **Slack**: 1 request per second per workspace
|
||||
- **Gotify**: No strict limits (self-hosted)
|
||||
|
||||
### 6. Keep Templates Maintainable
|
||||
|
||||
@@ -503,7 +327,7 @@ Be mindful of service limits:
|
||||
|
||||
## Advanced Use Cases
|
||||
|
||||
### Multi-Channel Routing
|
||||
### Routing by Severity
|
||||
|
||||
Create separate providers for different severity levels:
|
||||
|
||||
@@ -512,11 +336,11 @@ Provider: Discord Critical
|
||||
Events: uptime_down, ssl_failure
|
||||
Template: Custom with @everyone mention
|
||||
|
||||
Provider: Slack Info
|
||||
Provider: Discord Info
|
||||
Events: ssl_renewal, backup_success
|
||||
Template: Minimal
|
||||
|
||||
Provider: Gotify All
|
||||
Provider: Discord All
|
||||
Events: * (all)
|
||||
Template: Detailed
|
||||
```
|
||||
@@ -554,8 +378,6 @@ Forward notifications to automation tools:
|
||||
## Additional Resources
|
||||
|
||||
- [Discord Webhook Documentation](https://discord.com/developers/docs/resources/webhook)
|
||||
- [Slack Block Kit Builder](https://api.slack.com/block-kit)
|
||||
- [Gotify API Documentation](https://gotify.net/docs/)
|
||||
- [Charon Security Guide](../security.md)
|
||||
|
||||
## Need Help?
|
||||
|
||||
Reference in New Issue
Block a user