浏览代码

add sentinel notification plugin (#2268)

blotus 2 年之前
父节点
当前提交
77d58652a3

+ 1 - 0
.gitignore

@@ -46,6 +46,7 @@ plugins/notifications/slack/notification-slack
 plugins/notifications/splunk/notification-splunk
 plugins/notifications/splunk/notification-splunk
 plugins/notifications/email/notification-email
 plugins/notifications/email/notification-email
 plugins/notifications/dummy/notification-dummy
 plugins/notifications/dummy/notification-dummy
+plugins/notifications/sentinel/notification-sentinel
 
 
 # Test cache (downloaded files)
 # Test cache (downloaded files)
 .cache
 .cache

+ 1 - 0
Dockerfile

@@ -56,6 +56,7 @@ COPY --from=build /go/src/crowdsec/plugins/notifications/email/email.yaml /stagi
 COPY --from=build /go/src/crowdsec/plugins/notifications/http/http.yaml /staging/etc/crowdsec/notifications/http.yaml
 COPY --from=build /go/src/crowdsec/plugins/notifications/http/http.yaml /staging/etc/crowdsec/notifications/http.yaml
 COPY --from=build /go/src/crowdsec/plugins/notifications/slack/slack.yaml /staging/etc/crowdsec/notifications/slack.yaml
 COPY --from=build /go/src/crowdsec/plugins/notifications/slack/slack.yaml /staging/etc/crowdsec/notifications/slack.yaml
 COPY --from=build /go/src/crowdsec/plugins/notifications/splunk/splunk.yaml /staging/etc/crowdsec/notifications/splunk.yaml
 COPY --from=build /go/src/crowdsec/plugins/notifications/splunk/splunk.yaml /staging/etc/crowdsec/notifications/splunk.yaml
+COPY --from=build /go/src/crowdsec/plugins/notifications/sentinel/sentinel.yaml /staging/etc/crowdsec/notifications/sentinel.yaml
 COPY --from=build /usr/local/lib/crowdsec/plugins /usr/local/lib/crowdsec/plugins
 COPY --from=build /usr/local/lib/crowdsec/plugins /usr/local/lib/crowdsec/plugins
 
 
 FROM slim as geoip
 FROM slim as geoip

+ 1 - 0
Dockerfile.debian

@@ -72,6 +72,7 @@ COPY --from=build /go/src/crowdsec/plugins/notifications/email/email.yaml /stagi
 COPY --from=build /go/src/crowdsec/plugins/notifications/http/http.yaml /staging/etc/crowdsec/notifications/http.yaml
 COPY --from=build /go/src/crowdsec/plugins/notifications/http/http.yaml /staging/etc/crowdsec/notifications/http.yaml
 COPY --from=build /go/src/crowdsec/plugins/notifications/slack/slack.yaml /staging/etc/crowdsec/notifications/slack.yaml
 COPY --from=build /go/src/crowdsec/plugins/notifications/slack/slack.yaml /staging/etc/crowdsec/notifications/slack.yaml
 COPY --from=build /go/src/crowdsec/plugins/notifications/splunk/splunk.yaml /staging/etc/crowdsec/notifications/splunk.yaml
 COPY --from=build /go/src/crowdsec/plugins/notifications/splunk/splunk.yaml /staging/etc/crowdsec/notifications/splunk.yaml
+COPY --from=build /go/src/crowdsec/plugins/notifications/sentinel/sentinel.yaml /staging/etc/crowdsec/notifications/sentinel.yaml
 COPY --from=build /usr/local/lib/crowdsec/plugins /usr/local/lib/crowdsec/plugins
 COPY --from=build /usr/local/lib/crowdsec/plugins /usr/local/lib/crowdsec/plugins
 
 
 FROM slim as geoip
 FROM slim as geoip

+ 1 - 0
debian/install

@@ -10,3 +10,4 @@ plugins/notifications/slack/slack.yaml      etc/crowdsec/notifications/
 plugins/notifications/http/http.yaml        etc/crowdsec/notifications/
 plugins/notifications/http/http.yaml        etc/crowdsec/notifications/
 plugins/notifications/splunk/splunk.yaml    etc/crowdsec/notifications/
 plugins/notifications/splunk/splunk.yaml    etc/crowdsec/notifications/
 plugins/notifications/email/email.yaml      etc/crowdsec/notifications/
 plugins/notifications/email/email.yaml      etc/crowdsec/notifications/
+plugins/notifications/sentinel/sentinel.yaml      etc/crowdsec/notifications/

+ 1 - 0
debian/rules

@@ -29,6 +29,7 @@ override_dh_auto_install:
 	install -m 551 plugins/notifications/http/notification-http debian/crowdsec/usr/lib/crowdsec/plugins/
 	install -m 551 plugins/notifications/http/notification-http debian/crowdsec/usr/lib/crowdsec/plugins/
 	install -m 551 plugins/notifications/splunk/notification-splunk debian/crowdsec/usr/lib/crowdsec/plugins/
 	install -m 551 plugins/notifications/splunk/notification-splunk debian/crowdsec/usr/lib/crowdsec/plugins/
 	install -m 551 plugins/notifications/email/notification-email debian/crowdsec/usr/lib/crowdsec/plugins/
 	install -m 551 plugins/notifications/email/notification-email debian/crowdsec/usr/lib/crowdsec/plugins/
+	install -m 551 plugins/notifications/sentinel/notification-sentinel debian/crowdsec/usr/lib/crowdsec/plugins/
 
 
 	cp cmd/crowdsec/crowdsec debian/crowdsec/usr/bin
 	cp cmd/crowdsec/crowdsec debian/crowdsec/usr/bin
 	cp cmd/crowdsec-cli/cscli debian/crowdsec/usr/bin
 	cp cmd/crowdsec-cli/cscli debian/crowdsec/usr/bin

+ 2 - 0
docker/test/tests/test_flavors.py

@@ -50,9 +50,11 @@ def test_flavor_content(crowdsec, flavor):
             assert 'notification-http' not in stdout
             assert 'notification-http' not in stdout
             assert 'notification-slack' not in stdout
             assert 'notification-slack' not in stdout
             assert 'notification-splunk' not in stdout
             assert 'notification-splunk' not in stdout
+            assert 'notification-sentinel' not in stdout
         else:
         else:
             assert x.exit_code == 0
             assert x.exit_code == 0
             assert 'notification-email' in stdout
             assert 'notification-email' in stdout
             assert 'notification-http' in stdout
             assert 'notification-http' in stdout
             assert 'notification-slack' in stdout
             assert 'notification-slack' in stdout
             assert 'notification-splunk' in stdout
             assert 'notification-splunk' in stdout
+            assert 'notification-sentinel' in stdout

+ 17 - 0
plugins/notifications/sentinel/Makefile

@@ -0,0 +1,17 @@
+ifeq ($(OS), Windows_NT)
+	SHELL := pwsh.exe
+	.SHELLFLAGS := -NoProfile -Command
+	EXT = .exe
+endif
+
+# Go parameters
+GOCMD = go
+GOBUILD = $(GOCMD) build
+
+BINARY_NAME = notification-sentinel$(EXT)
+
+build: clean
+	$(GOBUILD) $(LD_OPTS) $(BUILD_VENDOR_FLAGS) -o $(BINARY_NAME)
+
+clean:
+	@$(RM) $(BINARY_NAME) $(WIN_IGNORE_ERR)

+ 28 - 0
plugins/notifications/sentinel/go.mod

@@ -0,0 +1,28 @@
+module github.com/crowdsecurity/sentinel-plugin
+
+go 1.20
+
+replace github.com/crowdsecurity/crowdsec => ../../../
+
+require (
+	github.com/crowdsecurity/crowdsec v1.5.0
+	github.com/hashicorp/go-hclog v1.5.0
+	github.com/hashicorp/go-plugin v1.4.10
+	gopkg.in/yaml.v3 v3.0.1
+)
+
+require (
+	github.com/fatih/color v1.15.0 // indirect
+	github.com/golang/protobuf v1.5.3 // indirect
+	github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb // indirect
+	github.com/mattn/go-colorable v0.1.13 // indirect
+	github.com/mattn/go-isatty v0.0.17 // indirect
+	github.com/mitchellh/go-testing-interface v1.0.0 // indirect
+	github.com/oklog/run v1.0.0 // indirect
+	golang.org/x/net v0.9.0 // indirect
+	golang.org/x/sys v0.9.0 // indirect
+	golang.org/x/text v0.9.0 // indirect
+	google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
+	google.golang.org/grpc v1.56.1 // indirect
+	google.golang.org/protobuf v1.30.0 // indirect
+)

+ 61 - 0
plugins/notifications/sentinel/go.sum

@@ -0,0 +1,61 @@
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
+github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
+github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
+github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
+github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c=
+github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
+github.com/hashicorp/go-plugin v1.4.10 h1:xUbmA4jC6Dq163/fWcp8P3JuHilrHHMLNRxzGQJ9hNk=
+github.com/hashicorp/go-plugin v1.4.10/go.mod h1:6/1TEzT0eQznvI/gV2CM29DLSkAK/e58mUWKVsPaph0=
+github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb h1:b5rjCoWHc7eqmAS4/qyk21ZsHyb6Mxv/jykxvNTkU4M=
+github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
+github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE=
+github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
+github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
+github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
+github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
+github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
+github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
+github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
+github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
+github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
+github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0=
+github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
+github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw=
+github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
+github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
+golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
+golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
+golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s=
+golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
+golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A=
+google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU=
+google.golang.org/grpc v1.56.1 h1:z0dNfjIl0VpaZ9iSVjA6daGatAYwPGstTjt5vkRMFkQ=
+google.golang.org/grpc v1.56.1/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
+google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

+ 133 - 0
plugins/notifications/sentinel/main.go

@@ -0,0 +1,133 @@
+package main
+
+import (
+	"context"
+	"crypto/hmac"
+	"crypto/sha256"
+	"encoding/base64"
+	"fmt"
+	"net/http"
+	"os"
+	"strings"
+	"time"
+
+	"github.com/crowdsecurity/crowdsec/pkg/protobufs"
+	"github.com/hashicorp/go-hclog"
+	"github.com/hashicorp/go-plugin"
+	"gopkg.in/yaml.v3"
+)
+
+type PluginConfig struct {
+	Name       string  `yaml:"name"`
+	CustomerID string  `yaml:"customer_id"`
+	SharedKey  string  `yaml:"shared_key"`
+	LogType    string  `yaml:"log_type"`
+	LogLevel   *string `yaml:"log_level"`
+}
+
+type SentinelPlugin struct {
+	PluginConfigByName map[string]PluginConfig
+}
+
+var logger hclog.Logger = hclog.New(&hclog.LoggerOptions{
+	Name:       "sentinel-plugin",
+	Level:      hclog.LevelFromString("INFO"),
+	Output:     os.Stderr,
+	JSONFormat: true,
+})
+
+func (s *SentinelPlugin) getAuthorizationHeader(now string, length int, pluginName string) (string, error) {
+	xHeaders := "x-ms-date:" + now
+
+	stringToHash := fmt.Sprintf("POST\n%d\napplication/json\n%s\n/api/logs", length, xHeaders)
+	decodedKey, _ := base64.StdEncoding.DecodeString(s.PluginConfigByName[pluginName].SharedKey)
+
+	h := hmac.New(sha256.New, decodedKey)
+	h.Write([]byte(stringToHash))
+
+	encodedHash := base64.StdEncoding.EncodeToString(h.Sum(nil))
+	authorization := "SharedKey " + s.PluginConfigByName[pluginName].CustomerID + ":" + encodedHash
+
+	logger.Trace("authorization header", "header", authorization)
+
+	return authorization, nil
+}
+
+func (s *SentinelPlugin) Notify(ctx context.Context, notification *protobufs.Notification) (*protobufs.Empty, error) {
+
+	if _, ok := s.PluginConfigByName[notification.Name]; !ok {
+		return nil, fmt.Errorf("invalid plugin config name %s", notification.Name)
+	}
+	cfg := s.PluginConfigByName[notification.Name]
+
+	if cfg.LogLevel != nil && *cfg.LogLevel != "" {
+		logger.SetLevel(hclog.LevelFromString(*cfg.LogLevel))
+	}
+
+	logger.Info("received notification for sentinel config", "name", notification.Name)
+
+	url := fmt.Sprintf("https://%s.ods.opinsights.azure.com/api/logs?api-version=2016-04-01", s.PluginConfigByName[notification.Name].CustomerID)
+	body := strings.NewReader(notification.Text)
+
+	//Cannot use time.RFC1123 as azure wants GMT, not UTC
+	now := time.Now().UTC().Format("Mon, 02 Jan 2006 15:04:05 GMT")
+
+	authorization, err := s.getAuthorizationHeader(now, len(notification.Text), notification.Name)
+
+	if err != nil {
+		return &protobufs.Empty{}, err
+	}
+
+	req, err := http.NewRequest("POST", url, body)
+	if err != nil {
+		logger.Error("failed to create request", "error", err)
+		return &protobufs.Empty{}, err
+	}
+
+	req.Header.Set("Content-Type", "application/json")
+	req.Header.Set("Log-Type", s.PluginConfigByName[notification.Name].LogType)
+	req.Header.Set("Authorization", authorization)
+	req.Header.Set("x-ms-date", now)
+
+	client := &http.Client{}
+	resp, err := client.Do(req)
+	if err != nil {
+		logger.Error("failed to send request", "error", err)
+		return &protobufs.Empty{}, err
+	}
+	defer resp.Body.Close()
+	logger.Debug("sent notification to sentinel", "status", resp.Status)
+
+	if resp.StatusCode != 200 {
+		return &protobufs.Empty{}, fmt.Errorf("failed to send notification to sentinel: %s", resp.Status)
+	}
+
+	return &protobufs.Empty{}, nil
+}
+
+func (s *SentinelPlugin) Configure(ctx context.Context, config *protobufs.Config) (*protobufs.Empty, error) {
+	d := PluginConfig{}
+	err := yaml.Unmarshal(config.Config, &d)
+	s.PluginConfigByName[d.Name] = d
+	return &protobufs.Empty{}, err
+}
+
+func main() {
+	var handshake = plugin.HandshakeConfig{
+		ProtocolVersion:  1,
+		MagicCookieKey:   "CROWDSEC_PLUGIN_KEY",
+		MagicCookieValue: os.Getenv("CROWDSEC_PLUGIN_KEY"),
+	}
+
+	sp := &SentinelPlugin{PluginConfigByName: make(map[string]PluginConfig)}
+	plugin.Serve(&plugin.ServeConfig{
+		HandshakeConfig: handshake,
+		Plugins: map[string]plugin.Plugin{
+			"sentinel": &protobufs.NotifierPlugin{
+				Impl: sp,
+			},
+		},
+		GRPCServer: plugin.DefaultGRPCServer,
+		Logger:     logger,
+	})
+}

+ 21 - 0
plugins/notifications/sentinel/sentinel.yaml

@@ -0,0 +1,21 @@
+type: sentinel          # Don't change
+name: sentinel_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:            # Time to wait for response from the plugin before considering the attempt a failure, eg "10s"
+
+#-------------------------
+# plugin-specific options
+
+# The following template receives a list of models.Alert objects
+# The output goes in the http request body
+format: |
+  {{.|toJson}}
+
+customer_id: XXX-XXX
+shared_key: XXXXXXX
+log_type: crowdsec

+ 4 - 0
rpm/SPECS/crowdsec.spec

@@ -67,11 +67,14 @@ install -m 551 plugins/notifications/slack/notification-slack %{buildroot}%{_lib
 install -m 551 plugins/notifications/http/notification-http %{buildroot}%{_libdir}/%{name}/plugins/
 install -m 551 plugins/notifications/http/notification-http %{buildroot}%{_libdir}/%{name}/plugins/
 install -m 551 plugins/notifications/splunk/notification-splunk %{buildroot}%{_libdir}/%{name}/plugins/
 install -m 551 plugins/notifications/splunk/notification-splunk %{buildroot}%{_libdir}/%{name}/plugins/
 install -m 551 plugins/notifications/email/notification-email %{buildroot}%{_libdir}/%{name}/plugins/
 install -m 551 plugins/notifications/email/notification-email %{buildroot}%{_libdir}/%{name}/plugins/
+install -m 551 plugins/notifications/sentinel/notification-sentinel %{buildroot}%{_libdir}/%{name}/plugins/
 
 
 install -m 600 plugins/notifications/slack/slack.yaml %{buildroot}%{_sysconfdir}/crowdsec/notifications/
 install -m 600 plugins/notifications/slack/slack.yaml %{buildroot}%{_sysconfdir}/crowdsec/notifications/
 install -m 600 plugins/notifications/http/http.yaml %{buildroot}%{_sysconfdir}/crowdsec/notifications/
 install -m 600 plugins/notifications/http/http.yaml %{buildroot}%{_sysconfdir}/crowdsec/notifications/
 install -m 600 plugins/notifications/splunk/splunk.yaml %{buildroot}%{_sysconfdir}/crowdsec/notifications/
 install -m 600 plugins/notifications/splunk/splunk.yaml %{buildroot}%{_sysconfdir}/crowdsec/notifications/
 install -m 600 plugins/notifications/email/email.yaml %{buildroot}%{_sysconfdir}/crowdsec/notifications/
 install -m 600 plugins/notifications/email/email.yaml %{buildroot}%{_sysconfdir}/crowdsec/notifications/
+install -m 600 plugins/notifications/sentinel/sentinel.yaml %{buildroot}%{_sysconfdir}/crowdsec/notifications/
+
 
 
 %clean
 %clean
 rm -rf %{buildroot}
 rm -rf %{buildroot}
@@ -85,6 +88,7 @@ rm -rf %{buildroot}
 %{_libdir}/%{name}/plugins/notification-http
 %{_libdir}/%{name}/plugins/notification-http
 %{_libdir}/%{name}/plugins/notification-splunk
 %{_libdir}/%{name}/plugins/notification-splunk
 %{_libdir}/%{name}/plugins/notification-email
 %{_libdir}/%{name}/plugins/notification-email
+%{_libdir}/%{name}/plugins/notification-sentinel
 %{_sysconfdir}/%{name}/patterns/linux-syslog
 %{_sysconfdir}/%{name}/patterns/linux-syslog
 %{_sysconfdir}/%{name}/patterns/ruby
 %{_sysconfdir}/%{name}/patterns/ruby
 %{_sysconfdir}/%{name}/patterns/nginx
 %{_sysconfdir}/%{name}/patterns/nginx

+ 1 - 1
scripts/test_env.ps1

@@ -71,7 +71,7 @@ $parser_s02="$parser_dir\s02-enrich"
 $scenarios_dir="$config_dir\scenarios"
 $scenarios_dir="$config_dir\scenarios"
 $postoverflows_dir="$config_dir\postoverflows"
 $postoverflows_dir="$config_dir\postoverflows"
 $hub_dir="$config_dir\hub"
 $hub_dir="$config_dir\hub"
-$plugins=@("http", "slack", "splunk")
+$plugins=@("http", "slack", "splunk", "email", "sentinel")
 $plugins_dir="plugins"
 $plugins_dir="plugins"
 $notif_dir="notifications"
 $notif_dir="notifications"
 
 

+ 1 - 1
scripts/test_env.sh

@@ -47,7 +47,7 @@ PARSER_S02="$PARSER_DIR/s02-enrich"
 SCENARIOS_DIR="$CONFIG_DIR/scenarios"
 SCENARIOS_DIR="$CONFIG_DIR/scenarios"
 POSTOVERFLOWS_DIR="$CONFIG_DIR/postoverflows"
 POSTOVERFLOWS_DIR="$CONFIG_DIR/postoverflows"
 HUB_DIR="$CONFIG_DIR/hub"
 HUB_DIR="$CONFIG_DIR/hub"
-PLUGINS="http slack splunk email"
+PLUGINS="http slack splunk email sentinel"
 PLUGINS_DIR="plugins"
 PLUGINS_DIR="plugins"
 NOTIF_DIR="notifications"
 NOTIF_DIR="notifications"
 
 

+ 1 - 1
test/lib/config/config-local

@@ -76,7 +76,7 @@ config_generate() {
 	    type: syslog
 	    type: syslog
 	EOT
 	EOT
 
 
-    cp ../plugins/notifications/*/{http,email,slack,splunk,dummy}.yaml \
+    cp ../plugins/notifications/*/{http,email,slack,splunk,dummy,sentinel}.yaml \
        "${CONFIG_DIR}/notifications/"
        "${CONFIG_DIR}/notifications/"
 
 
     yq e '
     yq e '

+ 5 - 1
windows/installer/product.wxs

@@ -99,6 +99,9 @@
                         <File Id="splunk.yaml" Source="plugins\notifications\splunk\splunk.yaml" Name="splunk.yaml">
                         <File Id="splunk.yaml" Source="plugins\notifications\splunk\splunk.yaml" Name="splunk.yaml">
                            <PermissionEx Sddl="D:PAI(A;;FA;;;SY)(A;;FA;;;BA)"/>
                            <PermissionEx Sddl="D:PAI(A;;FA;;;SY)(A;;FA;;;BA)"/>
                         </File>
                         </File>
+                        <File Id="sentinel.yaml" Source="plugins\notifications\sentinel\sentinel.yaml" Name="sentinel.yaml">
+                           <PermissionEx Sddl="D:PAI(A;;FA;;;SY)(A;;FA;;;BA)"/>
+                        </File>
                      </Component>
                      </Component>
                   </Directory>
                   </Directory>
                   <Directory Id="PatternsDir" Name="patterns" />
                   <Directory Id="PatternsDir" Name="patterns" />
@@ -124,6 +127,7 @@
                      <File Id="notification_email.exe" Source="plugins\notifications\email\notification-email.exe" />
                      <File Id="notification_email.exe" Source="plugins\notifications\email\notification-email.exe" />
                      <File Id="notification_http.exe" Source="plugins\notifications\http\notification-http.exe" />
                      <File Id="notification_http.exe" Source="plugins\notifications\http\notification-http.exe" />
                      <File Id="notification_splunk.exe" Source="plugins\notifications\splunk\notification-splunk.exe" />
                      <File Id="notification_splunk.exe" Source="plugins\notifications\splunk\notification-splunk.exe" />
+                     <File Id="notification_sentinel.exe" Source="plugins\notifications\sentinel\notification-sentinel.exe" />
                   </Component>
                   </Component>
                </Directory>
                </Directory>
             </Directory>
             </Directory>
@@ -186,4 +190,4 @@
 
 
    </Product>
    </Product>
 
 
-</Wix>
+</Wix>

+ 5 - 0
wizard.sh

@@ -81,11 +81,14 @@ HTTP_PLUGIN_BINARY="./plugins/notifications/http/notification-http"
 SLACK_PLUGIN_BINARY="./plugins/notifications/slack/notification-slack"
 SLACK_PLUGIN_BINARY="./plugins/notifications/slack/notification-slack"
 SPLUNK_PLUGIN_BINARY="./plugins/notifications/splunk/notification-splunk"
 SPLUNK_PLUGIN_BINARY="./plugins/notifications/splunk/notification-splunk"
 EMAIL_PLUGIN_BINARY="./plugins/notifications/email/notification-email"
 EMAIL_PLUGIN_BINARY="./plugins/notifications/email/notification-email"
+SENTINEL_PLUGIN_BINARY="./plugins/notifications/sentinel/notification-sentinel"
 
 
 HTTP_PLUGIN_CONFIG="./plugins/notifications/http/http.yaml"
 HTTP_PLUGIN_CONFIG="./plugins/notifications/http/http.yaml"
 SLACK_PLUGIN_CONFIG="./plugins/notifications/slack/slack.yaml"
 SLACK_PLUGIN_CONFIG="./plugins/notifications/slack/slack.yaml"
 SPLUNK_PLUGIN_CONFIG="./plugins/notifications/splunk/splunk.yaml"
 SPLUNK_PLUGIN_CONFIG="./plugins/notifications/splunk/splunk.yaml"
 EMAIL_PLUGIN_CONFIG="./plugins/notifications/email/email.yaml"
 EMAIL_PLUGIN_CONFIG="./plugins/notifications/email/email.yaml"
+SENTINEL_PLUGIN_CONFIG="./plugins/notifications/sentinel/sentinel.yaml"
+
 
 
 BACKUP_DIR=$(mktemp -d)
 BACKUP_DIR=$(mktemp -d)
 rm -rf -- "$BACKUP_DIR"
 rm -rf -- "$BACKUP_DIR"
@@ -518,12 +521,14 @@ install_plugins(){
     cp ${SPLUNK_PLUGIN_BINARY} ${CROWDSEC_PLUGIN_DIR}
     cp ${SPLUNK_PLUGIN_BINARY} ${CROWDSEC_PLUGIN_DIR}
     cp ${HTTP_PLUGIN_BINARY} ${CROWDSEC_PLUGIN_DIR}
     cp ${HTTP_PLUGIN_BINARY} ${CROWDSEC_PLUGIN_DIR}
     cp ${EMAIL_PLUGIN_BINARY} ${CROWDSEC_PLUGIN_DIR}
     cp ${EMAIL_PLUGIN_BINARY} ${CROWDSEC_PLUGIN_DIR}
+    cp ${SENTINEL_PLUGIN_BINARY} ${CROWDSEC_PLUGIN_DIR}
 
 
     if [[ ${DOCKER_MODE} == "false" ]]; then
     if [[ ${DOCKER_MODE} == "false" ]]; then
         cp -n ${SLACK_PLUGIN_CONFIG} /etc/crowdsec/notifications/
         cp -n ${SLACK_PLUGIN_CONFIG} /etc/crowdsec/notifications/
         cp -n ${SPLUNK_PLUGIN_CONFIG} /etc/crowdsec/notifications/
         cp -n ${SPLUNK_PLUGIN_CONFIG} /etc/crowdsec/notifications/
         cp -n ${HTTP_PLUGIN_CONFIG} /etc/crowdsec/notifications/
         cp -n ${HTTP_PLUGIN_CONFIG} /etc/crowdsec/notifications/
         cp -n ${EMAIL_PLUGIN_CONFIG} /etc/crowdsec/notifications/
         cp -n ${EMAIL_PLUGIN_CONFIG} /etc/crowdsec/notifications/
+        cp -n ${SENTINEL_PLUGIN_CONFIG} /etc/crowdsec/notifications/
     fi
     fi
 }
 }