Alerting

Sentinel includes a built-in alerting system that sends real-time notifications when security events occur. Alerts are dispatched to one or more providers — Slack, email, or a custom webhook — whenever a threat event meets or exceeds your configured severity threshold. This lets your security team respond immediately to attacks without watching the dashboard around the clock.

Pipeline Integration

The alerting system is implemented as a pipeline handler. It processes threat events asynchronously alongside other handlers like the threat profiler and geolocation enricher. No events are dropped or delayed by alert dispatch.

Alert Providers

Sentinel supports three alert providers out of the box. You can enable any combination of them — all three can run simultaneously.

ProviderChannelDescription
SlackslackSends rich formatted messages to a Slack channel via an incoming webhook URL.
EmailemailSends HTML-formatted alert emails via SMTP to one or more recipients.
WebhookwebhookSends a JSON payload via HTTP POST to any custom URL, with optional custom headers.

Configuration

Alerting is configured through the Alerts field on the main sentinel.Config struct. Each provider is enabled by providing its corresponding config pointer — nil means the provider is disabled.

AlertConfig

FieldTypeDefaultDescription
MinSeveritySeverityHighMinimum severity level required to trigger an alert. Events below this threshold are silently ignored.
Slack*SlackConfignilSlack webhook configuration. Set to enable Slack alerts.
Email*EmailConfignilEmail SMTP configuration. Set to enable email alerts.
Webhook*WebhookConfignilCustom webhook configuration. Set to enable webhook alerts.

SlackConfig

FieldTypeDescription
WebhookURLstringThe Slack incoming webhook URL. Create one at api.slack.com/messaging/webhooks.

EmailConfig

FieldTypeDescription
SMTPHoststringSMTP server hostname (e.g., smtp.gmail.com).
SMTPPortintSMTP server port (e.g., 587 for TLS).
UsernamestringSMTP authentication username, also used as the From address.
PasswordstringSMTP authentication password or app-specific password.
Recipients[]stringList of email addresses to receive alerts.

WebhookConfig

FieldTypeDescription
URLstringThe endpoint URL that receives the JSON POST request.
Headersmap[string]stringOptional custom HTTP headers to include with every request (e.g., authorization tokens).
core/config.gogo
1// AlertConfig configures the alerting system.
2type AlertConfig struct {
3 MinSeverity Severity `json:"min_severity"`
4 Slack *SlackConfig `json:"slack,omitempty"`
5 Email *EmailConfig `json:"email,omitempty"`
6 Webhook *WebhookConfig `json:"webhook,omitempty"`
7}
8
9// SlackConfig configures Slack webhook alerts.
10type SlackConfig struct {
11 WebhookURL string `json:"webhook_url"`
12}
13
14// EmailConfig configures email alerts.
15type EmailConfig struct {
16 SMTPHost string `json:"smtp_host"`
17 SMTPPort int `json:"smtp_port"`
18 Username string `json:"username"`
19 Password string `json:"password"`
20 Recipients []string `json:"recipients"`
21}
22
23// WebhookConfig configures generic webhook alerts.
24type WebhookConfig struct {
25 URL string `json:"url"`
26 Headers map[string]string `json:"headers,omitempty"`
27}

Severity Filtering

The MinSeverity field controls which threat events trigger alerts. Only events with a severity equal to or greater than the configured threshold are dispatched. Events below the threshold are silently discarded by the alert dispatcher.

SeverityLevelDescription
Low1Minor events such as informational detections. Alerts on everything.
Medium2Moderate events such as suspicious patterns. Skips Low events.
High3Serious events such as confirmed attack attempts. Default threshold.
Critical4Only the most severe events trigger alerts. Use for low-noise channels.

Default Severity

When MinSeverity is not set, it defaults to High. This means only High and Critical events trigger alerts by default. Set it to sentinel.SeverityLow if you want to be alerted on all events, but be aware this can be noisy in high-traffic environments.
1// Alert on everything (noisy)
2Alerts: sentinel.AlertConfig{
3 MinSeverity: sentinel.SeverityLow,
4 // ...providers
5}
6
7// Alert only on critical events (quiet)
8Alerts: sentinel.AlertConfig{
9 MinSeverity: sentinel.SeverityCritical,
10 // ...providers
11}

How It Works

The alert Dispatcher is registered as a handler in the Sentinel event pipeline. When any detection feature (WAF, Auth Shield, Anomaly Detection, Rate Limiting) produces a threat event, the pipeline delivers it to the dispatcher. The dispatcher then:

  1. Checks the severity threshold — if the event severity is below MinSeverity, it is ignored.
  2. Deduplicates — repeated alerts for the same IP and threat type combination are suppressed within a 5-minute window to prevent alert fatigue.
  3. Dispatches concurrently — the event is sent to all configured providers in parallel. A failure in one provider does not affect the others.
  4. Retries on failure — each provider has up to 3 attempts with exponential backoff (1s, 2s, 4s) before the alert is marked as failed.
  5. Records history — every dispatch attempt (success or failure) is recorded in the alert history, which is accessible via the dashboard and API.

Deduplication

The dispatcher automatically suppresses duplicate alerts for the same IP and threat type within a 5-minute window. If an attacker triggers 100 SQL injection events in a row, you receive one alert, not 100. After 5 minutes, a new alert is sent if the attack is still ongoing.

Slack Integration

The Slack provider sends rich formatted messages using Slack Block Kit. Each alert includes the severity level, threat type, source IP (with country if geolocation is enabled), the targeted route, whether the request was blocked, and the timestamp.

Configuration

main.gogo
1sentinel.Mount(r, nil, sentinel.Config{
2 WAF: sentinel.WAFConfig{
3 Enabled: true,
4 Mode: sentinel.ModeBlock,
5 },
6 Alerts: sentinel.AlertConfig{
7 MinSeverity: sentinel.SeverityHigh,
8 Slack: &sentinel.SlackConfig{
9 WebhookURL: "https://hooks.slack.com/services/T00/B00/xxxx",
10 },
11 },
12})

Message Format

Slack alerts are formatted with Block Kit sections. The message includes a header with a severity indicator, a divider, and a details section:

--- Slack message ---
High Threat Detected
────────────────────
Type: SQLInjection
IP: 203.0.113.50 (United States)
Route: GET /api/users?id=1' OR '1'='1
Blocked: Yes
Time: 2025-01-15T14:30:00Z

Slack Webhook Setup

To create a Slack webhook URL, go to api.slack.com/apps, create a new app (or select an existing one), enable Incoming Webhooks, and add a new webhook to the channel where you want to receive alerts. Copy the generated URL into your Sentinel config.

Email Integration

The email provider sends HTML-formatted alert emails via SMTP. Each email includes the severity level, threat type, source IP, targeted route, block status, and timestamp in a styled table layout.

Configuration

main.gogo
1sentinel.Mount(r, nil, sentinel.Config{
2 WAF: sentinel.WAFConfig{
3 Enabled: true,
4 Mode: sentinel.ModeBlock,
5 },
6 Alerts: sentinel.AlertConfig{
7 MinSeverity: sentinel.SeverityHigh,
8 Email: &sentinel.EmailConfig{
9 SMTPHost: "smtp.gmail.com",
10 SMTPPort: 587,
11 Username: "alerts@yourcompany.com",
12 Password: "your-app-specific-password",
13 Recipients: []string{
14 "security-team@yourcompany.com",
15 "oncall@yourcompany.com",
16 },
17 },
18 },
19})

The email subject line follows the format: [Sentinel] High Threat: SQLInjection from 203.0.113.50. The body is an HTML table with the same details as the Slack message, styled for readability in email clients.

Gmail App Passwords

If you use Gmail as your SMTP provider, you need to generate an app-specific password rather than using your regular account password. Go to your Google Account security settings and create an app password under 2-Step Verification. Use that password in the Password field.

Webhook Integration

The webhook provider sends a JSON payload via HTTP POST to any URL you specify. This is ideal for integrating with custom SIEM systems, PagerDuty, Opsgenie, Datadog, or any service that accepts JSON webhooks. You can include custom headers for authentication.

Configuration

main.gogo
1sentinel.Mount(r, nil, sentinel.Config{
2 WAF: sentinel.WAFConfig{
3 Enabled: true,
4 Mode: sentinel.ModeBlock,
5 },
6 Alerts: sentinel.AlertConfig{
7 MinSeverity: sentinel.SeverityMedium,
8 Webhook: &sentinel.WebhookConfig{
9 URL: "https://your-siem.example.com/api/v1/events",
10 Headers: map[string]string{
11 "Authorization": "Bearer your-api-token",
12 "X-Source": "sentinel",
13 },
14 },
15 },
16})

JSON Payload Structure

Every webhook request sends a JSON payload with the following fields:

Webhook Payloadjson
{
"event": "threat_detected",
"threat_id": "te-abc123",
"timestamp": "2025-01-15T14:30:00Z",
"ip": "203.0.113.50",
"method": "GET",
"path": "/api/users",
"threat_types": ["SQLInjection"],
"severity": "High",
"confidence": 95,
"blocked": true,
"country": "United States",
"evidence": "1' OR '1'='1"
}
FieldTypeDescription
eventstringAlways "threat_detected".
threat_idstringUnique identifier for the threat event.
timestampstringISO 8601 / RFC 3339 timestamp in UTC.
ipstringSource IP address of the attacker.
methodstringHTTP method of the request (GET, POST, etc.).
pathstringRequest path that triggered the detection.
threat_types[]stringList of detected threat types (e.g., SQLInjection, XSS).
severitystringSeverity level: Low, Medium, High, or Critical.
confidenceintDetection confidence score (0-100).
blockedboolWhether the request was blocked by the WAF.
countrystringCountry of origin (empty if geolocation is not enabled).
evidencestringThe matched pattern or payload snippet that triggered the detection.

Response Handling

The webhook provider expects a 2xx status code from the receiving endpoint. Any non-2xx response triggers the retry mechanism (up to 3 attempts with exponential backoff). The request has a 10-second timeout per attempt.

Multiple Providers

You can configure all three providers simultaneously. When a qualifying threat event occurs, the dispatcher sends alerts to every configured provider concurrently. A failure in one provider does not prevent the others from receiving the alert.

main.gogo
1sentinel.Mount(r, nil, sentinel.Config{
2 WAF: sentinel.WAFConfig{
3 Enabled: true,
4 Mode: sentinel.ModeBlock,
5 },
6 Alerts: sentinel.AlertConfig{
7 MinSeverity: sentinel.SeverityHigh,
8
9 // Slack for real-time team notifications
10 Slack: &sentinel.SlackConfig{
11 WebhookURL: "https://hooks.slack.com/services/T00/B00/xxxx",
12 },
13
14 // Email for the security team
15 Email: &sentinel.EmailConfig{
16 SMTPHost: "smtp.gmail.com",
17 SMTPPort: 587,
18 Username: "alerts@yourcompany.com",
19 Password: "your-app-specific-password",
20 Recipients: []string{"security-team@yourcompany.com"},
21 },
22
23 // Webhook for SIEM integration
24 Webhook: &sentinel.WebhookConfig{
25 URL: "https://your-siem.example.com/api/v1/events",
26 Headers: map[string]string{
27 "Authorization": "Bearer your-siem-token",
28 },
29 },
30 },
31})

Independent Delivery

Each provider runs in its own goroutine with independent retry logic. If your SMTP server is temporarily unreachable, Slack and webhook alerts still go through. Failed attempts are recorded in the alert history with the error message for debugging.

Alert History

Every alert dispatch attempt is recorded in an in-memory history log. Each entry tracks whether the alert was sent successfully or failed, along with the channel, severity, IP, threat type, and any error message.

AlertHistory Fields

FieldTypeDescription
IDstringUnique identifier for the history entry.
Timestamptime.TimeWhen the alert was dispatched.
ThreatIDstringThe ID of the threat event that triggered the alert.
ChannelstringThe provider channel: slack, email, or webhook.
SeveritySeveritySeverity of the threat event.
IPstringSource IP of the attacker.
ThreatTypestringThe primary threat type that triggered the alert.
SuccessboolWhether the alert was delivered successfully.
ErrorstringError message if the alert failed (empty on success).

The history buffer retains the last 1,000 entries in memory. Older entries are evicted when new ones arrive. The history resets on application restart.

Dashboard

The Sentinel dashboard includes a dedicated Alerts page that provides visibility into your alerting configuration and delivery history.

  • Configuration overview — see which providers are active, the current severity threshold, and the connection details for each provider.
  • Alert history — browse the chronological log of all dispatched alerts with their delivery status, channel, severity, source IP, and threat type.
  • Failure tracking — quickly identify failed deliveries and their error messages to diagnose connectivity or configuration issues.

Access the Alerts page at http://localhost:8080/sentinel/ui and navigate to the Alerts section.

Full Configuration Example

The following example enables the WAF in block mode with Slack alerting for high-severity events and a webhook for SIEM integration at medium severity:

main.gogo
1package main
2
3import (
4 sentinel "github.com/MUKE-coder/sentinel"
5 "github.com/gin-gonic/gin"
6)
7
8func main() {
9 r := gin.Default()
10
11 sentinel.Mount(r, nil, sentinel.Config{
12 WAF: sentinel.WAFConfig{
13 Enabled: true,
14 Mode: sentinel.ModeBlock,
15 },
16
17 Alerts: sentinel.AlertConfig{
18 MinSeverity: sentinel.SeverityHigh,
19
20 Slack: &sentinel.SlackConfig{
21 WebhookURL: "https://hooks.slack.com/services/T00/B00/xxxx",
22 },
23
24 Email: &sentinel.EmailConfig{
25 SMTPHost: "smtp.gmail.com",
26 SMTPPort: 587,
27 Username: "alerts@yourcompany.com",
28 Password: "your-app-specific-password",
29 Recipients: []string{
30 "security-team@yourcompany.com",
31 },
32 },
33
34 Webhook: &sentinel.WebhookConfig{
35 URL: "https://your-siem.example.com/api/v1/events",
36 Headers: map[string]string{
37 "Authorization": "Bearer your-siem-token",
38 },
39 },
40 },
41 })
42
43 r.GET("/api/data", func(c *gin.Context) {
44 c.JSON(200, gin.H{"status": "ok"})
45 })
46
47 r.Run(":8080")
48}

Next Steps

  • WAF — Configure the detection rules that generate threat events
  • Auth Shield — Protect login endpoints and generate auth-related alerts
  • Anomaly Detection — Add behavioral analysis that feeds into alerting
  • Threat Intelligence — Profile attackers and enrich alert data with geolocation
  • Dashboard — View alert history and configuration in the UI

Built with by JB