mirror of
https://github.com/crowdsecurity/crowdsec.git
synced 2025-05-10 20:05:55 +02:00
Add plugin to send notification to alertmanager
This commit is contained in:
parent
c4bfdf1991
commit
55e045023b
4 changed files with 166 additions and 0 deletions
17
cmd/notification-alertmanager/Makefile
Normal file
17
cmd/notification-alertmanager/Makefile
Normal 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)
|
25
cmd/notification-alertmanager/alertmanager.yaml
Normal file
25
cmd/notification-alertmanager/alertmanager.yaml
Normal 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
|
50
cmd/notification-alertmanager/main.go
Normal file
50
cmd/notification-alertmanager/main.go
Normal 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,
|
||||
})
|
||||
}
|
74
cmd/notification-alertmanager/plugin.go
Normal file
74
cmd/notification-alertmanager/plugin.go
Normal 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
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue