mirror of
https://github.com/crowdsecurity/crowdsec.git
synced 2025-05-14 13:24:34 +02:00
233 lines
5.2 KiB
Go
233 lines
5.2 KiB
Go
//go:build windows
|
|
// +build windows
|
|
|
|
package wineventlogacquisition
|
|
|
|
import (
|
|
"runtime"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/crowdsecurity/crowdsec/pkg/exprhelpers"
|
|
"github.com/crowdsecurity/crowdsec/pkg/types"
|
|
log "github.com/sirupsen/logrus"
|
|
"github.com/stretchr/testify/assert"
|
|
"golang.org/x/sys/windows/svc/eventlog"
|
|
"gopkg.in/tomb.v2"
|
|
)
|
|
|
|
func TestBadConfiguration(t *testing.T) {
|
|
if runtime.GOOS != "windows" {
|
|
t.Skip("Skipping test on non-windows OS")
|
|
}
|
|
tests := []struct {
|
|
config string
|
|
expectedErr string
|
|
}{
|
|
{
|
|
config: `source: wineventlog
|
|
foobar: 42`,
|
|
expectedErr: "field foobar not found in type wineventlogacquisition.WinEventLogConfiguration",
|
|
},
|
|
{
|
|
config: `source: wineventlog`,
|
|
expectedErr: "event_channel or xpath_query must be set",
|
|
},
|
|
{
|
|
config: `source: wineventlog
|
|
event_channel: Security
|
|
event_level: blabla`,
|
|
expectedErr: "buildXpathQuery failed: invalid log level",
|
|
},
|
|
{
|
|
config: `source: wineventlog
|
|
event_channel: Security
|
|
event_level: blabla`,
|
|
expectedErr: "buildXpathQuery failed: invalid log level",
|
|
},
|
|
{
|
|
config: `source: wineventlog
|
|
event_channel: foo
|
|
xpath_query: test`,
|
|
expectedErr: "event_channel and xpath_query are mutually exclusive",
|
|
},
|
|
}
|
|
|
|
subLogger := log.WithFields(log.Fields{
|
|
"type": "windowseventlog",
|
|
})
|
|
for _, test := range tests {
|
|
f := WinEventLogSource{}
|
|
err := f.Configure([]byte(test.config), subLogger)
|
|
assert.Contains(t, err.Error(), test.expectedErr)
|
|
}
|
|
}
|
|
|
|
func TestQueryBuilder(t *testing.T) {
|
|
if runtime.GOOS != "windows" {
|
|
t.Skip("Skipping test on non-windows OS")
|
|
}
|
|
tests := []struct {
|
|
config string
|
|
expectedQuery string
|
|
expectedErr string
|
|
}{
|
|
{
|
|
config: `source: wineventlog
|
|
event_channel: Security
|
|
event_level: Information`,
|
|
expectedQuery: "<QueryList><Query><Select Path=\"Security\">*[System[(Level=0 or Level=4)]]</Select></Query></QueryList>",
|
|
expectedErr: "",
|
|
},
|
|
{
|
|
config: `source: wineventlog
|
|
event_channel: Security
|
|
event_level: Error
|
|
event_ids:
|
|
- 42`,
|
|
expectedQuery: "<QueryList><Query><Select Path=\"Security\">*[System[(EventID=42) and (Level=2)]]</Select></Query></QueryList>",
|
|
expectedErr: "",
|
|
},
|
|
{
|
|
config: `source: wineventlog
|
|
event_channel: Security
|
|
event_level: Error
|
|
event_ids:
|
|
- 42
|
|
- 43`,
|
|
expectedQuery: "<QueryList><Query><Select Path=\"Security\">*[System[(EventID=42 or EventID=43) and (Level=2)]]</Select></Query></QueryList>",
|
|
expectedErr: "",
|
|
},
|
|
{
|
|
config: `source: wineventlog
|
|
event_channel: Security`,
|
|
expectedQuery: "<QueryList><Query><Select Path=\"Security\">*</Select></Query></QueryList>",
|
|
expectedErr: "",
|
|
},
|
|
{
|
|
config: `source: wineventlog
|
|
event_channel: Security
|
|
event_level: bla`,
|
|
expectedQuery: "",
|
|
expectedErr: "invalid log level",
|
|
},
|
|
}
|
|
subLogger := log.WithFields(log.Fields{
|
|
"type": "windowseventlog",
|
|
})
|
|
for _, test := range tests {
|
|
f := WinEventLogSource{}
|
|
f.Configure([]byte(test.config), subLogger)
|
|
q, err := f.buildXpathQuery()
|
|
if test.expectedErr != "" {
|
|
if err == nil {
|
|
t.Fatalf("expected error '%s' but got none", test.expectedErr)
|
|
}
|
|
assert.Contains(t, err.Error(), test.expectedErr)
|
|
} else {
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, test.expectedQuery, q)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestLiveAcquisition(t *testing.T) {
|
|
if runtime.GOOS != "windows" {
|
|
t.Skip("Skipping test on non-windows OS")
|
|
}
|
|
|
|
tests := []struct {
|
|
config string
|
|
expectedLines []string
|
|
}{
|
|
{
|
|
config: `source: wineventlog
|
|
xpath_query: |
|
|
<QueryList>
|
|
<Query Id="0" Path="Application">
|
|
<Select Path="Application">*[System[(Level=4 or Level=0) and (EventID=42)]]</Select>
|
|
</Query>
|
|
</QueryList>`,
|
|
expectedLines: []string{
|
|
"blabla",
|
|
"test",
|
|
"aaaa",
|
|
"bbbbb",
|
|
},
|
|
},
|
|
{
|
|
config: `source: wineventlog
|
|
xpath_query: |
|
|
<sdf>asdfsdf`,
|
|
expectedLines: nil,
|
|
},
|
|
{
|
|
config: `source: wineventlog
|
|
event_channel: Application
|
|
event_level: Information
|
|
event_ids:
|
|
- 42`,
|
|
expectedLines: []string{
|
|
"testmessage",
|
|
},
|
|
},
|
|
{
|
|
config: `source: wineventlog
|
|
event_channel: Application
|
|
event_level: Information
|
|
event_ids:
|
|
- 43`,
|
|
expectedLines: nil,
|
|
},
|
|
}
|
|
subLogger := log.WithFields(log.Fields{
|
|
"type": "windowseventlog",
|
|
})
|
|
|
|
evthandler, err := eventlog.Open("Application")
|
|
|
|
if err != nil {
|
|
t.Fatalf("failed to open event log: %s", err)
|
|
}
|
|
|
|
for _, test := range tests {
|
|
to := &tomb.Tomb{}
|
|
c := make(chan types.Event)
|
|
f := WinEventLogSource{}
|
|
f.Configure([]byte(test.config), subLogger)
|
|
f.StreamingAcquisition(c, to)
|
|
time.Sleep(time.Second)
|
|
lines := test.expectedLines
|
|
go func() {
|
|
for _, line := range lines {
|
|
evthandler.Info(42, line)
|
|
}
|
|
}()
|
|
ticker := time.NewTicker(time.Second * 5)
|
|
linesRead := make([]string, 0)
|
|
READLOOP:
|
|
for {
|
|
select {
|
|
case <-ticker.C:
|
|
if test.expectedLines == nil {
|
|
break READLOOP
|
|
}
|
|
t.Fatalf("timeout")
|
|
case e := <-c:
|
|
|
|
linesRead = append(linesRead, exprhelpers.XMLGetNodeValue(e.Line.Raw, "/Event/EventData[1]/Data"))
|
|
if len(linesRead) == len(lines) {
|
|
break READLOOP
|
|
}
|
|
}
|
|
}
|
|
if test.expectedLines == nil {
|
|
assert.Equal(t, 0, len(linesRead))
|
|
} else {
|
|
assert.Equal(t, len(test.expectedLines), len(linesRead))
|
|
assert.Equal(t, test.expectedLines, linesRead)
|
|
}
|
|
to.Kill(nil)
|
|
to.Wait()
|
|
}
|
|
}
|