123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257 |
- //go:build windows
- package csplugin
- import (
- "log"
- "os"
- "os/exec"
- "path"
- "path/filepath"
- "reflect"
- "testing"
- "time"
- "github.com/crowdsecurity/crowdsec/pkg/csconfig"
- "github.com/crowdsecurity/crowdsec/pkg/models"
- "github.com/crowdsecurity/crowdsec/pkg/types"
- "github.com/stretchr/testify/assert"
- "gopkg.in/tomb.v2"
- )
- /*
- Due to the complexity of file permission modification with go on windows, we only test the basic behavior the broker,
- not if it will actually reject plugins with invalid permissions
- */
- var testPath string
- func TestGetPluginNameAndTypeFromPath(t *testing.T) {
- setUp()
- defer tearDown()
- type args struct {
- path string
- }
- tests := []struct {
- name string
- args args
- want string
- want1 string
- wantErr bool
- }{
- {
- name: "valid plugin name, single dash",
- args: args{
- path: path.Join(testPath, "notification-gitter"),
- },
- want: "notification",
- want1: "gitter",
- wantErr: false,
- },
- {
- name: "invalid plugin name",
- args: args{
- path: ".\\tests\\gitter.exe",
- },
- want: "",
- want1: "",
- wantErr: true,
- },
- {
- name: "valid plugin name, multiple dash",
- args: args{
- path: ".\\tests\\notification-instant-slack.exe",
- },
- want: "notification-instant",
- want1: "slack",
- wantErr: false,
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- got, got1, err := getPluginTypeAndSubtypeFromPath(tt.args.path)
- if (err != nil) != tt.wantErr {
- t.Errorf("getPluginNameAndTypeFromPath() error = %v, wantErr %v", err, tt.wantErr)
- return
- }
- if got != tt.want {
- t.Errorf("getPluginNameAndTypeFromPath() got = %v, want %v", got, tt.want)
- }
- if got1 != tt.want1 {
- t.Errorf("getPluginNameAndTypeFromPath() got1 = %v, want %v", got1, tt.want1)
- }
- })
- }
- }
- func TestListFilesAtPath(t *testing.T) {
- setUp()
- defer tearDown()
- type args struct {
- path string
- }
- tests := []struct {
- name string
- args args
- want []string
- wantErr bool
- }{
- {
- name: "valid directory",
- args: args{
- path: testPath,
- },
- want: []string{
- filepath.Join(testPath, "notification-gitter"),
- filepath.Join(testPath, "slack"),
- },
- },
- {
- name: "invalid directory",
- args: args{
- path: "./foo/bar/",
- },
- wantErr: true,
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- got, err := listFilesAtPath(tt.args.path)
- if (err != nil) != tt.wantErr {
- t.Errorf("listFilesAtPath() error = %v, wantErr %v", err, tt.wantErr)
- return
- }
- if !reflect.DeepEqual(got, tt.want) {
- t.Errorf("listFilesAtPath() = %v, want %v", got, tt.want)
- }
- })
- }
- }
- func TestBrokerInit(t *testing.T) {
- tests := []struct {
- name string
- action func()
- errContains string
- wantErr bool
- procCfg csconfig.PluginCfg
- }{
- {
- name: "valid config",
- wantErr: false,
- },
- {
- name: "no plugin dir",
- wantErr: true,
- errContains: "The system cannot find the file specified.",
- action: tearDown,
- },
- {
- name: "no plugin binary",
- wantErr: true,
- errContains: "binary for plugin dummy_default not found",
- action: func() {
- err := os.Remove(path.Join(testPath, "notification-dummy.exe"))
- if err != nil {
- t.Fatal(err)
- }
- },
- },
- }
- for _, test := range tests {
- t.Run(test.name, func(t *testing.T) {
- defer tearDown()
- buildDummyPlugin()
- if test.action != nil {
- test.action()
- }
- pb := PluginBroker{}
- profiles := csconfig.NewDefaultConfig().API.Server.Profiles
- profiles = append(profiles, &csconfig.ProfileCfg{
- Notifications: []string{"dummy_default"},
- })
- err := pb.Init(&test.procCfg, profiles, &csconfig.ConfigurationPaths{
- PluginDir: testPath,
- NotificationDir: "./tests/notifications",
- })
- defer pb.Kill()
- if test.wantErr {
- assert.ErrorContains(t, err, test.errContains)
- } else {
- assert.NoError(t, err)
- }
- })
- }
- }
- func TestBrokerRun(t *testing.T) {
- buildDummyPlugin()
- defer tearDown()
- procCfg := csconfig.PluginCfg{}
- pb := PluginBroker{}
- profiles := csconfig.NewDefaultConfig().API.Server.Profiles
- profiles = append(profiles, &csconfig.ProfileCfg{
- Notifications: []string{"dummy_default"},
- })
- err := pb.Init(&procCfg, profiles, &csconfig.ConfigurationPaths{
- PluginDir: testPath,
- NotificationDir: "./tests/notifications",
- })
- assert.NoError(t, err)
- tomb := tomb.Tomb{}
- go pb.Run(&tomb)
- defer pb.Kill()
- assert.NoFileExists(t, "./out")
- defer os.Remove("./out")
- pb.PluginChannel <- ProfileAlert{ProfileID: uint(0), Alert: &models.Alert{}}
- pb.PluginChannel <- ProfileAlert{ProfileID: uint(0), Alert: &models.Alert{}}
- time.Sleep(time.Second * 4)
- assert.FileExists(t, ".\\out")
- assert.Equal(t, types.GetLineCountForFile(".\\out"), 2)
- }
- func buildDummyPlugin() {
- dir, err := os.MkdirTemp(".\\tests", "cs_plugin_test")
- if err != nil {
- log.Fatal(err)
- }
- cmd := exec.Command("go", "build", "-o", path.Join(dir, "notification-dummy.exe"), "../../plugins/notifications/dummy/")
- if err := cmd.Run(); err != nil {
- log.Fatal(err)
- }
- testPath = dir
- }
- func setUp() {
- dir, err := os.MkdirTemp("./", "cs_plugin_test")
- if err != nil {
- log.Fatal(err)
- }
- f, err := os.Create(path.Join(dir, "slack"))
- if err != nil {
- log.Fatal(err)
- }
- f.Close()
- f, err = os.Create(path.Join(dir, "notification-gitter"))
- if err != nil {
- log.Fatal(err)
- }
- f.Close()
- err = os.Mkdir(path.Join(dir, "dummy_dir"), 0666)
- if err != nil {
- log.Fatal(err)
- }
- testPath = dir
- }
- func tearDown() {
- err := os.RemoveAll(testPath)
- if err != nil {
- log.Fatal(err)
- }
- }
|