Initial commit
This commit is contained in:
commit
9f78f7a655
5 changed files with 1231 additions and 0 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
notification-telegram
|
||||||
|
.idea/
|
||||||
|
|
34
Makefile
Normal file
34
Makefile
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
# Go parameters
|
||||||
|
GOCMD=go
|
||||||
|
GOBUILD=$(GOCMD) build
|
||||||
|
GOCLEAN=$(GOCMD) clean
|
||||||
|
GOTEST=$(GOCMD) test
|
||||||
|
GOGET=$(GOCMD) get
|
||||||
|
LD_OPTS_STATIC=-ldflags "-s -w -extldflags '-static'"
|
||||||
|
BINARY_NAME=notification-telegram
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@$(RM) "$(BINARY_NAME)"
|
||||||
|
|
||||||
|
build: clean
|
||||||
|
$(GOBUILD) $(LD_OPTS_STATIC) -o $(BINARY_NAME) -a -tags netgo
|
||||||
|
|
||||||
|
deploy: build
|
||||||
|
cp $(BINARY_NAME) /usr/local/lib/crowdsec/plugins/
|
||||||
|
chown root:root /usr/local/lib/crowdsec/plugins/$(BINARY_NAME)
|
||||||
|
systemctl restart crowdsec
|
||||||
|
|
||||||
|
docker-deploy: build
|
||||||
|
docker cp $(BINARY_NAME) crowdsec:/usr/local/lib/crowdsec/plugins/
|
||||||
|
docker exec crowdsec chown root:root /usr/local/lib/crowdsec/plugins/$(BINARY_NAME)
|
||||||
|
docker restart crowdsec
|
||||||
|
|
||||||
|
test: deploy
|
||||||
|
while ! cscli decisions delete --ip 1.2.3.4 --debug; do continue; done
|
||||||
|
cscli decisions add --ip 1.2.3.4 --debug
|
||||||
|
cscli decisions delete --ip 1.2.3.4 --debug
|
||||||
|
|
||||||
|
docker-test: docker-deploy
|
||||||
|
while ! docker exec crowdsec cscli decisions delete --ip 1.2.3.4 --debug; do continue; done
|
||||||
|
docker exec crowdsec cscli decisions add --ip 1.2.3.4 --debug
|
||||||
|
docker exec crowdsec cscli decisions delete --ip 1.2.3.4 --debug
|
32
go.mod
Normal file
32
go.mod
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
module crowdsec-notification-telegram
|
||||||
|
|
||||||
|
go 1.17
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/crowdsecurity/crowdsec v1.3.0
|
||||||
|
github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1
|
||||||
|
github.com/hashicorp/go-hclog v1.1.0
|
||||||
|
github.com/hashicorp/go-plugin v1.4.3
|
||||||
|
gopkg.in/yaml.v2 v2.4.0
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/enescakir/emoji v1.0.0 // indirect
|
||||||
|
github.com/fatih/color v1.13.0 // indirect
|
||||||
|
github.com/golang/protobuf v1.5.2 // indirect
|
||||||
|
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb // indirect
|
||||||
|
github.com/kr/pretty v0.3.0 // indirect
|
||||||
|
github.com/mattn/go-colorable v0.1.9 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||||
|
github.com/mitchellh/go-testing-interface v1.0.0 // indirect
|
||||||
|
github.com/oklog/run v1.0.0 // indirect
|
||||||
|
github.com/rogpeppe/go-internal v1.8.0 // indirect
|
||||||
|
golang.org/x/net v0.0.0-20211209124913-491a49abca63 // indirect
|
||||||
|
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect
|
||||||
|
golang.org/x/text v0.3.7 // indirect
|
||||||
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||||
|
google.golang.org/genproto v0.0.0-20210114201628-6edceaf6022f // indirect
|
||||||
|
google.golang.org/grpc v1.35.0 // indirect
|
||||||
|
google.golang.org/protobuf v1.27.1 // indirect
|
||||||
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||||
|
)
|
144
main.go
Normal file
144
main.go
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"github.com/enescakir/emoji"
|
||||||
|
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/crowdsecurity/crowdsec/pkg/protobufs"
|
||||||
|
"github.com/hashicorp/go-hclog"
|
||||||
|
plugin "github.com/hashicorp/go-plugin"
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
var logger hclog.Logger = hclog.New(&hclog.LoggerOptions{
|
||||||
|
Name: "telegram-plugin",
|
||||||
|
Level: hclog.LevelFromString("DEBUG"),
|
||||||
|
Output: os.Stderr,
|
||||||
|
JSONFormat: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
type PluginConfig struct {
|
||||||
|
Name string `yaml:"name"`
|
||||||
|
LogLevel *string `yaml:"log_level"`
|
||||||
|
|
||||||
|
BotToken string `yaml:"bot_token"`
|
||||||
|
ChannelID int64 `yaml:"channel_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TelegramPlugin struct {
|
||||||
|
ConfigByName map[string]PluginConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
type Datas struct {
|
||||||
|
Message string `json:"message"`
|
||||||
|
Image string `json:"image,omitempty"`
|
||||||
|
Country string `json:"country,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *TelegramPlugin) 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 *TelegramPlugin) 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)
|
||||||
|
}
|
||||||
|
|
||||||
|
var datas []Datas
|
||||||
|
err := json.Unmarshal([]byte(notification.Text), &datas)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error(err.Error())
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
bot, err := tgbotapi.NewBotAPI(cfg.BotToken)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error(err.Error())
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
//bot.Debug = true // ToDo alling with logger level
|
||||||
|
|
||||||
|
logger.Info(fmt.Sprintf("Authorized on account %s", bot.Self.UserName))
|
||||||
|
|
||||||
|
for _, data := range datas {
|
||||||
|
var flag emoji.Emoji
|
||||||
|
if len(data.Country) != 0 {
|
||||||
|
flag, err = emoji.CountryFlag(data.Country)
|
||||||
|
}
|
||||||
|
if len(data.Country) == 0 || err != nil {
|
||||||
|
flag = emoji.PirateFlag
|
||||||
|
}
|
||||||
|
data.Message = strings.Replace(data.Message, ":flag:", string(flag), -1)
|
||||||
|
data.Message = strings.Replace(data.Message, ".", "\\.", -1)
|
||||||
|
data.Message = strings.Replace(data.Message, "-", "\\-", -1)
|
||||||
|
|
||||||
|
var msg tgbotapi.Chattable
|
||||||
|
if len(data.Image) != 0 {
|
||||||
|
response, err := http.Get(data.Image)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer response.Body.Close()
|
||||||
|
|
||||||
|
if response.StatusCode != 200 {
|
||||||
|
return nil, errors.New("received non 200 response code for image")
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpMsg := tgbotapi.NewPhoto(cfg.ChannelID, tgbotapi.FileReader{Name: "map.png", Reader: response.Body})
|
||||||
|
tmpMsg.Caption = data.Message
|
||||||
|
tmpMsg.ParseMode = tgbotapi.ModeMarkdownV2
|
||||||
|
msg = tmpMsg
|
||||||
|
} else {
|
||||||
|
tmpMsg := tgbotapi.NewMessage(cfg.ChannelID, data.Message)
|
||||||
|
tmpMsg.ParseMode = tgbotapi.ModeMarkdownV2
|
||||||
|
tmpMsg.DisableWebPagePreview = true
|
||||||
|
msg = tmpMsg
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = bot.Send(msg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &protobufs.Empty{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
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{
|
||||||
|
"telegram": &protobufs.NotifierPlugin{
|
||||||
|
Impl: &TelegramPlugin{ConfigByName: make(map[string]PluginConfig)},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
GRPCServer: plugin.DefaultGRPCServer,
|
||||||
|
Logger: logger,
|
||||||
|
})
|
||||||
|
}
|
Loading…
Reference in a new issue