Add plugin to send notification to alertmanager

This commit is contained in:
Yacine SAIBI 2024-07-16 16:21:30 +02:00
parent c4bfdf1991
commit 55e045023b
4 changed files with 166 additions and 0 deletions

View file

@ -0,0 +1,17 @@
ifeq ($(OS), Windows_NT)
SHELL := pwsh.exe
.SHELLFLAGS := -NoProfile -Command
EXT = .exe
endif
GO = go
GOBUILD = $(GO) build
BINARY_NAME = notification-alertmanager$(EXT)
build: clean
$(GOBUILD) $(LD_OPTS) -o $(BINARY_NAME)
.PHONY: clean
clean:
@$(RM) $(BINARY_NAME) $(WIN_IGNORE_ERR)

View file

@ -0,0 +1,25 @@
type: alertmanager # Don't change
name: alertmanager_default # Must match the registered plugin in the profile
# One of "trace", "debug", "info", "warn", "error", "off"
log_level: info
# group_wait: # Time to wait collecting alerts before relaying a message to this plugin, eg "30s"
# group_threshold: # Amount of alerts that triggers a message before <group_wait> has expired, eg "10"
# max_retry: # Number of attempts to relay messages to plugins in case of error
timeout: 20s # Time to wait for response from the plugin before considering the attempt a failure, eg "10s"
#-------------------------
# plugin-specific options
format: |
{{.|toJson}}
loglevel: "info"
host: "alertmanager_host_url"
user: "alertmanager username"
password: "alertmanager password"
basepath: "/api/v1"
schemes: ["https"]
source: "cluster_1" # source of the alert (cluster_name, server_name,...)
team: "infra_team" # the team in charge for this source or scope

View file

@ -0,0 +1,50 @@
package main
import (
"os"
protobufs "github.com/crowdsecurity/crowdsec/pkg/protobufs"
hclog "github.com/hashicorp/go-hclog"
plugin "github.com/hashicorp/go-plugin"
)
var logger hclog.Logger = hclog.New(&hclog.LoggerOptions{
Name: "alertmanager-plugin",
Level: hclog.LevelFromString("DEBUG"),
Output: os.Stderr,
JSONFormat: true,
})
type PluginConfig struct {
Name string
LogLevel *string
Host string
BasePath string
Schemes []string
User string
Password string
Source string
Team string
}
func main() {
var handshake = plugin.HandshakeConfig{
ProtocolVersion: 1,
MagicCookieKey: "CROWDSEC_PLUGIN_KEY",
MagicCookieValue: os.Getenv("CROWDSEC_PLUGIN_KEY"),
}
plugin.Serve(&plugin.ServeConfig{
HandshakeConfig: handshake,
Plugins: map[string]plugin.Plugin{
"alertmanager": &protobufs.NotifierPlugin{
Impl: &AlertmanagerPlugin{
ConfigByName: make(map[string]PluginConfig),
},
},
},
GRPCServer: plugin.DefaultGRPCServer,
Logger: logger,
})
}

View file

@ -0,0 +1,74 @@
package main
import (
"context"
"fmt"
"time"
protobufs "github.com/crowdsecurity/crowdsec/pkg/protobufs"
runtime "github.com/go-openapi/runtime/client"
strfmt "github.com/go-openapi/strfmt"
hclog "github.com/hashicorp/go-hclog"
alert "github.com/prometheus/alertmanager/api/v2/client/alert"
"github.com/prometheus/alertmanager/api/v2/models"
yaml "gopkg.in/yaml.v2"
)
type AlertmanagerPlugin struct {
ConfigByName map[string]PluginConfig
}
func (n *AlertmanagerPlugin) Configure(ctx context.Context, config *protobufs.Config) (*protobufs.Empty, error) {
d := PluginConfig{}
if err := yaml.Unmarshal(config.Config, &d); err != nil {
return nil, err
}
n.ConfigByName[d.Name] = d
return &protobufs.Empty{}, nil
}
func (n *AlertmanagerPlugin) Notify(ctx context.Context, notification *protobufs.Notification) (*protobufs.Empty, error) {
if _, ok := n.ConfigByName[notification.Name]; !ok {
return nil, fmt.Errorf("invalid plugin config name %s", notification.Name)
}
cfg := n.ConfigByName[notification.Name]
if cfg.LogLevel != nil && *cfg.LogLevel != "" {
logger.SetLevel(hclog.LevelFromString(*cfg.LogLevel))
} else {
logger.SetLevel(hclog.Info)
}
format := strfmt.NewFormats()
transport := runtime.New(cfg.Host, cfg.BasePath, cfg.Schemes)
transport.DefaultAuthentication = runtime.BasicAuth(cfg.User, cfg.Password)
client := alert.New(transport, format)
alertParams := n.createPostAlertParams(ctx, cfg, notification)
_, err := client.PostAlerts(alertParams)
if err != nil {
logger.Error("ErreurPostAlerts:", err.Error())
return nil, err
} else {
logger.Info(fmt.Sprintf(" %s ", notification.Name))
}
return &protobufs.Empty{}, nil
}
func (n *AlertmanagerPlugin) createPostAlertParams(ctx context.Context, cfg PluginConfig, notification *protobufs.Notification) *alert.PostAlertsParams {
alertParams := alert.NewPostAlertsParams()
now := time.Now()
params := &models.PostableAlert{
StartsAt: strfmt.DateTime(now),
EndsAt: strfmt.DateTime(now.Add(5 * time.Minute)),
Alert: models.Alert{
Labels: models.LabelSet{
"alertname": "crowdsec_alert",
"source": cfg.Source,
"team": cfg.Team,
"text": notification.Text,
},
},
}
alertParams.Alerts = models.PostableAlerts{params}
return alertParams
}