Skip to content

Commit

Permalink
plugins: use yaml.v3 (crowdsecurity#2969)
Browse files Browse the repository at this point in the history
* plugins: use yaml.v3

* lint
  • Loading branch information
mmetc authored Apr 25, 2024
1 parent 2abc078 commit d2c4bc5
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 28 deletions.
5 changes: 0 additions & 5 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,6 @@ linters-settings:
- "!**/pkg/apiserver/controllers/v1/errors.go"
yaml:
files:
- "!**/cmd/notification-dummy/main.go"
- "!**/cmd/notification-email/main.go"
- "!**/cmd/notification-http/main.go"
- "!**/cmd/notification-slack/main.go"
- "!**/cmd/notification-splunk/main.go"
- "!**/pkg/acquisition/acquisition.go"
- "!**/pkg/acquisition/acquisition_test.go"
- "!**/pkg/acquisition/modules/appsec/appsec.go"
Expand Down
14 changes: 10 additions & 4 deletions cmd/notification-dummy/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ import (
"fmt"
"os"

"github.com/crowdsecurity/crowdsec/pkg/protobufs"
"github.com/hashicorp/go-hclog"
plugin "github.com/hashicorp/go-plugin"
"gopkg.in/yaml.v2"
"gopkg.in/yaml.v3"

"github.com/crowdsecurity/crowdsec/pkg/protobufs"
)

type PluginConfig struct {
Expand All @@ -32,6 +33,7 @@ func (s *DummyPlugin) Notify(ctx context.Context, notification *protobufs.Notifi
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 != "" {
Expand All @@ -42,19 +44,22 @@ func (s *DummyPlugin) Notify(ctx context.Context, notification *protobufs.Notifi
logger.Debug(notification.Text)

if cfg.OutputFile != nil && *cfg.OutputFile != "" {
f, err := os.OpenFile(*cfg.OutputFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
f, err := os.OpenFile(*cfg.OutputFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644)
if err != nil {
logger.Error(fmt.Sprintf("Cannot open notification file: %s", err))
}

if _, err := f.WriteString(notification.Text + "\n"); err != nil {
f.Close()
logger.Error(fmt.Sprintf("Cannot write notification to file: %s", err))
}

err = f.Close()
if err != nil {
logger.Error(fmt.Sprintf("Cannot close notification file: %s", err))
}
}

fmt.Println(notification.Text)

return &protobufs.Empty{}, nil
Expand All @@ -64,11 +69,12 @@ func (s *DummyPlugin) Configure(ctx context.Context, config *protobufs.Config) (
d := PluginConfig{}
err := yaml.Unmarshal(config.Config, &d)
s.PluginConfigByName[d.Name] = d

return &protobufs.Empty{}, err
}

func main() {
var handshake = plugin.HandshakeConfig{
handshake := plugin.HandshakeConfig{
ProtocolVersion: 1,
MagicCookieKey: "CROWDSEC_PLUGIN_KEY",
MagicCookieValue: os.Getenv("CROWDSEC_PLUGIN_KEY"),
Expand Down
22 changes: 16 additions & 6 deletions cmd/notification-email/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@ package main

import (
"context"
"errors"
"fmt"
"os"
"time"

"github.com/crowdsecurity/crowdsec/pkg/protobufs"
"github.com/hashicorp/go-hclog"
plugin "github.com/hashicorp/go-plugin"
mail "github.com/xhit/go-simple-mail/v2"
"gopkg.in/yaml.v2"
"gopkg.in/yaml.v3"

"github.com/crowdsecurity/crowdsec/pkg/protobufs"
)

var baseLogger hclog.Logger = hclog.New(&hclog.LoggerOptions{
Expand Down Expand Up @@ -72,26 +74,28 @@ func (n *EmailPlugin) Configure(ctx context.Context, config *protobufs.Config) (
}

if d.Name == "" {
return nil, fmt.Errorf("name is required")
return nil, errors.New("name is required")
}

if d.SMTPHost == "" {
return nil, fmt.Errorf("SMTP host is not set")
return nil, errors.New("SMTP host is not set")
}

if d.ReceiverEmails == nil || len(d.ReceiverEmails) == 0 {
return nil, fmt.Errorf("receiver emails are not set")
return nil, errors.New("receiver emails are not set")
}

n.ConfigByName[d.Name] = d
baseLogger.Debug(fmt.Sprintf("Email plugin '%s' use SMTP host '%s:%d'", d.Name, d.SMTPHost, d.SMTPPort))

return &protobufs.Empty{}, nil
}

func (n *EmailPlugin) 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]

logger := baseLogger.Named(cfg.Name)
Expand All @@ -117,6 +121,7 @@ func (n *EmailPlugin) Notify(ctx context.Context, notification *protobufs.Notifi
server.ConnectTimeout, err = time.ParseDuration(cfg.ConnectTimeout)
if err != nil {
logger.Warn(fmt.Sprintf("invalid connect timeout '%s', using default '10s'", cfg.ConnectTimeout))

server.ConnectTimeout = 10 * time.Second
}
}
Expand All @@ -125,15 +130,18 @@ func (n *EmailPlugin) Notify(ctx context.Context, notification *protobufs.Notifi
server.SendTimeout, err = time.ParseDuration(cfg.SendTimeout)
if err != nil {
logger.Warn(fmt.Sprintf("invalid send timeout '%s', using default '10s'", cfg.SendTimeout))

server.SendTimeout = 10 * time.Second
}
}

logger.Debug("making smtp connection")

smtpClient, err := server.Connect()
if err != nil {
return &protobufs.Empty{}, err
}

logger.Debug("smtp connection done")

email := mail.NewMSG()
Expand All @@ -146,12 +154,14 @@ func (n *EmailPlugin) Notify(ctx context.Context, notification *protobufs.Notifi
if err != nil {
return &protobufs.Empty{}, err
}

logger.Info(fmt.Sprintf("sent email to %v", cfg.ReceiverEmails))

return &protobufs.Empty{}, nil
}

func main() {
var handshake = plugin.HandshakeConfig{
handshake := plugin.HandshakeConfig{
ProtocolVersion: 1,
MagicCookieKey: "CROWDSEC_PLUGIN_KEY",
MagicCookieValue: os.Getenv("CROWDSEC_PLUGIN_KEY"),
Expand Down
23 changes: 19 additions & 4 deletions cmd/notification-http/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@ import (
"os"
"strings"

"github.com/crowdsecurity/crowdsec/pkg/protobufs"
"github.com/hashicorp/go-hclog"
plugin "github.com/hashicorp/go-plugin"
"gopkg.in/yaml.v2"
"gopkg.in/yaml.v3"

"github.com/crowdsecurity/crowdsec/pkg/protobufs"
)

type PluginConfig struct {
Expand Down Expand Up @@ -90,25 +91,31 @@ func getTLSClient(c *PluginConfig) error {

tlsConfig.Certificates = []tls.Certificate{cert}
}

transport := &http.Transport{
TLSClientConfig: tlsConfig,
}

if c.UnixSocket != "" {
logger.Info(fmt.Sprintf("Using socket '%s'", c.UnixSocket))

transport.DialContext = func(_ context.Context, _, _ string) (net.Conn, error) {
return net.Dial("unix", strings.TrimSuffix(c.UnixSocket, "/"))
}
}

c.Client = &http.Client{
Transport: transport,
}

return nil
}

func (s *HTTPPlugin) 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 != "" {
Expand All @@ -121,11 +128,14 @@ func (s *HTTPPlugin) Notify(ctx context.Context, notification *protobufs.Notific
if err != nil {
return nil, err
}

for headerName, headerValue := range cfg.Headers {
logger.Debug(fmt.Sprintf("adding header %s: %s", headerName, headerValue))
request.Header.Add(headerName, headerValue)
}

logger.Debug(fmt.Sprintf("making HTTP %s call to %s with body %s", cfg.Method, cfg.URL, notification.Text))

resp, err := cfg.Client.Do(request.WithContext(ctx))
if err != nil {
logger.Error(fmt.Sprintf("Failed to make HTTP request : %s", err))
Expand All @@ -135,14 +145,15 @@ func (s *HTTPPlugin) Notify(ctx context.Context, notification *protobufs.Notific

respData, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("failed to read response body got error %s", err)
return nil, fmt.Errorf("failed to read response body got error %w", err)
}

logger.Debug(fmt.Sprintf("got response %s", string(respData)))

if resp.StatusCode < 200 || resp.StatusCode >= 300 {
logger.Warn(fmt.Sprintf("HTTP server returned non 200 status code: %d", resp.StatusCode))
logger.Debug(fmt.Sprintf("HTTP server returned body: %s", string(respData)))

return &protobufs.Empty{}, nil
}

Expand All @@ -151,21 +162,25 @@ func (s *HTTPPlugin) Notify(ctx context.Context, notification *protobufs.Notific

func (s *HTTPPlugin) Configure(ctx context.Context, config *protobufs.Config) (*protobufs.Empty, error) {
d := PluginConfig{}

err := yaml.Unmarshal(config.Config, &d)
if err != nil {
return nil, err
}

err = getTLSClient(&d)
if err != nil {
return nil, err
}

s.PluginConfigByName[d.Name] = d
logger.Debug(fmt.Sprintf("HTTP plugin '%s' use URL '%s'", d.Name, d.URL))

return &protobufs.Empty{}, err
}

func main() {
var handshake = plugin.HandshakeConfig{
handshake := plugin.HandshakeConfig{
ProtocolVersion: 1,
MagicCookieKey: "CROWDSEC_PLUGIN_KEY",
MagicCookieValue: os.Getenv("CROWDSEC_PLUGIN_KEY"),
Expand Down
14 changes: 10 additions & 4 deletions cmd/notification-slack/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import (
"fmt"
"os"

"github.com/crowdsecurity/crowdsec/pkg/protobufs"
"github.com/hashicorp/go-hclog"
plugin "github.com/hashicorp/go-plugin"

"github.com/slack-go/slack"
"gopkg.in/yaml.v2"
"gopkg.in/yaml.v3"

"github.com/crowdsecurity/crowdsec/pkg/protobufs"
)

type PluginConfig struct {
Expand All @@ -33,13 +33,16 @@ func (n *Notify) Notify(ctx context.Context, notification *protobufs.Notificatio
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))
}

logger.Info(fmt.Sprintf("found notify signal for %s config", notification.Name))
logger.Debug(fmt.Sprintf("posting to %s webhook, message %s", cfg.Webhook, notification.Text))

err := slack.PostWebhookContext(ctx, n.ConfigByName[notification.Name].Webhook, &slack.WebhookMessage{
Text: notification.Text,
})
Expand All @@ -52,16 +55,19 @@ func (n *Notify) Notify(ctx context.Context, notification *protobufs.Notificatio

func (n *Notify) 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
logger.Debug(fmt.Sprintf("Slack plugin '%s' use URL '%s'", d.Name, d.Webhook))

return &protobufs.Empty{}, nil
}

func main() {
var handshake = plugin.HandshakeConfig{
handshake := plugin.HandshakeConfig{
ProtocolVersion: 1,
MagicCookieKey: "CROWDSEC_PLUGIN_KEY",
MagicCookieValue: os.Getenv("CROWDSEC_PLUGIN_KEY"),
Expand Down
18 changes: 13 additions & 5 deletions cmd/notification-splunk/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ import (
"os"
"strings"

"github.com/crowdsecurity/crowdsec/pkg/protobufs"
"github.com/hashicorp/go-hclog"
plugin "github.com/hashicorp/go-plugin"
"gopkg.in/yaml.v3"

"gopkg.in/yaml.v2"
"github.com/crowdsecurity/crowdsec/pkg/protobufs"
)

var logger hclog.Logger = hclog.New(&hclog.LoggerOptions{
Expand Down Expand Up @@ -44,6 +44,7 @@ func (s *Splunk) Notify(ctx context.Context, notification *protobufs.Notificatio
if _, ok := s.PluginConfigByName[notification.Name]; !ok {
return &protobufs.Empty{}, fmt.Errorf("splunk invalid config name %s", notification.Name)
}

cfg := s.PluginConfigByName[notification.Name]

if cfg.LogLevel != nil && *cfg.LogLevel != "" {
Expand All @@ -53,6 +54,7 @@ func (s *Splunk) Notify(ctx context.Context, notification *protobufs.Notificatio
logger.Info(fmt.Sprintf("received notify signal for %s config", notification.Name))

p := Payload{Event: notification.Text}

data, err := json.Marshal(p)
if err != nil {
return &protobufs.Empty{}, err
Expand All @@ -65,6 +67,7 @@ func (s *Splunk) Notify(ctx context.Context, notification *protobufs.Notificatio

req.Header.Add("Authorization", fmt.Sprintf("Splunk %s", cfg.Token))
logger.Debug(fmt.Sprintf("posting event %s to %s", string(data), req.URL))

resp, err := s.Client.Do(req.WithContext(ctx))
if err != nil {
return &protobufs.Empty{}, err
Expand All @@ -73,15 +76,19 @@ func (s *Splunk) Notify(ctx context.Context, notification *protobufs.Notificatio
if resp.StatusCode != http.StatusOK {
content, err := io.ReadAll(resp.Body)
if err != nil {
return &protobufs.Empty{}, fmt.Errorf("got non 200 response and failed to read error %s", err)
return &protobufs.Empty{}, fmt.Errorf("got non 200 response and failed to read error %w", err)
}

return &protobufs.Empty{}, fmt.Errorf("got non 200 response %s", string(content))
}

respData, err := io.ReadAll(resp.Body)
if err != nil {
return &protobufs.Empty{}, fmt.Errorf("failed to read response body got error %s", err)
return &protobufs.Empty{}, fmt.Errorf("failed to read response body got error %w", err)
}

logger.Debug(fmt.Sprintf("got response %s", string(respData)))

return &protobufs.Empty{}, nil
}

Expand All @@ -90,11 +97,12 @@ func (s *Splunk) Configure(ctx context.Context, config *protobufs.Config) (*prot
err := yaml.Unmarshal(config.Config, &d)
s.PluginConfigByName[d.Name] = d
logger.Debug(fmt.Sprintf("Splunk plugin '%s' use URL '%s'", d.Name, d.URL))

return &protobufs.Empty{}, err
}

func main() {
var handshake = plugin.HandshakeConfig{
handshake := plugin.HandshakeConfig{
ProtocolVersion: 1,
MagicCookieKey: "CROWDSEC_PLUGIN_KEY",
MagicCookieValue: os.Getenv("CROWDSEC_PLUGIN_KEY"),
Expand Down

0 comments on commit d2c4bc5

Please sign in to comment.