main.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. package main
  2. import (
  3. "context"
  4. "fmt"
  5. "os"
  6. "github.com/crowdsecurity/crowdsec/pkg/protobufs"
  7. "github.com/hashicorp/go-hclog"
  8. plugin "github.com/hashicorp/go-plugin"
  9. mail "github.com/xhit/go-simple-mail/v2"
  10. "gopkg.in/yaml.v2"
  11. )
  12. var baseLogger hclog.Logger = hclog.New(&hclog.LoggerOptions{
  13. Name: "email-plugin",
  14. Level: hclog.LevelFromString("INFO"),
  15. Output: os.Stderr,
  16. JSONFormat: true,
  17. })
  18. var AuthStringToType map[string]mail.AuthType = map[string]mail.AuthType{
  19. "none": mail.AuthNone,
  20. "crammd5": mail.AuthCRAMMD5,
  21. "login": mail.AuthLogin,
  22. "plain": mail.AuthPlain,
  23. }
  24. var EncryptionStringToType map[string]mail.Encryption = map[string]mail.Encryption{
  25. "ssltls": mail.EncryptionSSLTLS,
  26. "starttls": mail.EncryptionSTARTTLS,
  27. "none": mail.EncryptionNone,
  28. }
  29. type PluginConfig struct {
  30. Name string `yaml:"name"`
  31. LogLevel *string `yaml:"log_level"`
  32. SMTPHost string `yaml:"smtp_host"`
  33. SMTPPort int `yaml:"smtp_port"`
  34. SMTPUsername string `yaml:"smtp_username"`
  35. SMTPPassword string `yaml:"smtp_password"`
  36. SenderEmail string `yaml:"sender_email"`
  37. SenderName string `yaml:"sender_name"`
  38. ReceiverEmails []string `yaml:"receiver_emails"`
  39. EmailSubject string `yaml:"email_subject"`
  40. EncryptionType string `yaml:"encryption_type"`
  41. AuthType string `yaml:"auth_type"`
  42. }
  43. type EmailPlugin struct {
  44. ConfigByName map[string]PluginConfig
  45. }
  46. func (n *EmailPlugin) Configure(ctx context.Context, config *protobufs.Config) (*protobufs.Empty, error) {
  47. d := PluginConfig{
  48. SMTPPort: 25,
  49. SenderName: "Crowdsec",
  50. EmailSubject: "Crowdsec notification",
  51. EncryptionType: "ssltls",
  52. AuthType: "login",
  53. SenderEmail: "crowdsec@crowdsec.local",
  54. }
  55. if err := yaml.Unmarshal(config.Config, &d); err != nil {
  56. return nil, err
  57. }
  58. if d.Name == "" {
  59. return nil, fmt.Errorf("name is required")
  60. }
  61. if d.SMTPHost == "" {
  62. return nil, fmt.Errorf("SMTP host is not set")
  63. }
  64. if d.ReceiverEmails == nil || len(d.ReceiverEmails) == 0 {
  65. return nil, fmt.Errorf("Receiver emails are not set")
  66. }
  67. n.ConfigByName[d.Name] = d
  68. return &protobufs.Empty{}, nil
  69. }
  70. func (n *EmailPlugin) Notify(ctx context.Context, notification *protobufs.Notification) (*protobufs.Empty, error) {
  71. if _, ok := n.ConfigByName[notification.Name]; !ok {
  72. return nil, fmt.Errorf("invalid plugin config name %s", notification.Name)
  73. }
  74. cfg := n.ConfigByName[notification.Name]
  75. logger := baseLogger.Named(cfg.Name)
  76. if cfg.LogLevel != nil && *cfg.LogLevel != "" {
  77. logger.SetLevel(hclog.LevelFromString(*cfg.LogLevel))
  78. }
  79. logger.Debug("got notification")
  80. server := mail.NewSMTPClient()
  81. server.Host = cfg.SMTPHost
  82. server.Port = cfg.SMTPPort
  83. server.Username = cfg.SMTPUsername
  84. server.Password = cfg.SMTPPassword
  85. server.Encryption = EncryptionStringToType[cfg.EncryptionType]
  86. server.Authentication = AuthStringToType[cfg.AuthType]
  87. logger.Debug("making smtp connection")
  88. smtpClient, err := server.Connect()
  89. if err != nil {
  90. return &protobufs.Empty{}, err
  91. }
  92. logger.Debug("smtp connection done")
  93. email := mail.NewMSG()
  94. email.SetFrom(fmt.Sprintf("%s <%s>", cfg.SenderName, cfg.SenderEmail)).
  95. AddTo(cfg.ReceiverEmails...).
  96. SetSubject(cfg.EmailSubject)
  97. email.SetBody(mail.TextHTML, notification.Text)
  98. err = email.Send(smtpClient)
  99. if err != nil {
  100. return &protobufs.Empty{}, err
  101. }
  102. logger.Info(fmt.Sprintf("sent email to %v", cfg.ReceiverEmails))
  103. return &protobufs.Empty{}, nil
  104. }
  105. func main() {
  106. var handshake = plugin.HandshakeConfig{
  107. ProtocolVersion: 1,
  108. MagicCookieKey: "CROWDSEC_PLUGIN_KEY",
  109. MagicCookieValue: os.Getenv("CROWDSEC_PLUGIN_KEY"),
  110. }
  111. plugin.Serve(&plugin.ServeConfig{
  112. HandshakeConfig: handshake,
  113. Plugins: map[string]plugin.Plugin{
  114. "email": &protobufs.NotifierPlugin{
  115. Impl: &EmailPlugin{ConfigByName: make(map[string]PluginConfig)},
  116. },
  117. },
  118. GRPCServer: plugin.DefaultGRPCServer,
  119. Logger: baseLogger,
  120. })
  121. }