github.com/crowdsecurity/crowdsec@v1.6.1/pkg/acquisition/modules/wineventlog/wineventlog_test.go (about)

     1  //go:build windows
     2  
     3  package wineventlogacquisition
     4  
     5  import (
     6  	"runtime"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/crowdsecurity/crowdsec/pkg/acquisition/configuration"
    11  	"github.com/crowdsecurity/crowdsec/pkg/exprhelpers"
    12  	"github.com/crowdsecurity/crowdsec/pkg/types"
    13  	log "github.com/sirupsen/logrus"
    14  	"github.com/stretchr/testify/assert"
    15  	"github.com/stretchr/testify/require"
    16  	"golang.org/x/sys/windows/svc/eventlog"
    17  	"gopkg.in/tomb.v2"
    18  )
    19  
    20  func TestBadConfiguration(t *testing.T) {
    21  	if runtime.GOOS != "windows" {
    22  		t.Skip("Skipping test on non-windows OS")
    23  	}
    24  	tests := []struct {
    25  		config      string
    26  		expectedErr string
    27  	}{
    28  		{
    29  			config: `source: wineventlog
    30  foobar: 42`,
    31  			expectedErr: "field foobar not found in type wineventlogacquisition.WinEventLogConfiguration",
    32  		},
    33  		{
    34  			config:      `source: wineventlog`,
    35  			expectedErr: "event_channel or xpath_query must be set",
    36  		},
    37  		{
    38  			config: `source: wineventlog
    39  event_channel: Security
    40  event_level: blabla`,
    41  			expectedErr: "buildXpathQuery failed: invalid log level",
    42  		},
    43  		{
    44  			config: `source: wineventlog
    45  event_channel: Security
    46  event_level: blabla`,
    47  			expectedErr: "buildXpathQuery failed: invalid log level",
    48  		},
    49  		{
    50  			config: `source: wineventlog
    51  event_channel: foo
    52  xpath_query: test`,
    53  			expectedErr: "event_channel and xpath_query are mutually exclusive",
    54  		},
    55  	}
    56  
    57  	subLogger := log.WithFields(log.Fields{
    58  		"type": "windowseventlog",
    59  	})
    60  	for _, test := range tests {
    61  		f := WinEventLogSource{}
    62  		err := f.Configure([]byte(test.config), subLogger, configuration.METRICS_NONE)
    63  		assert.Contains(t, err.Error(), test.expectedErr)
    64  	}
    65  }
    66  
    67  func TestQueryBuilder(t *testing.T) {
    68  	if runtime.GOOS != "windows" {
    69  		t.Skip("Skipping test on non-windows OS")
    70  	}
    71  	tests := []struct {
    72  		config        string
    73  		expectedQuery string
    74  		expectedErr   string
    75  	}{
    76  		{
    77  			config: `source: wineventlog
    78  event_channel: Security
    79  event_level: Information`,
    80  			expectedQuery: "<QueryList><Query><Select Path=\"Security\">*[System[(Level=0 or Level=4)]]</Select></Query></QueryList>",
    81  			expectedErr:   "",
    82  		},
    83  		{
    84  			config: `source: wineventlog
    85  event_channel: Security
    86  event_level: Error
    87  event_ids:
    88   - 42`,
    89  			expectedQuery: "<QueryList><Query><Select Path=\"Security\">*[System[(EventID=42) and (Level=2)]]</Select></Query></QueryList>",
    90  			expectedErr:   "",
    91  		},
    92  		{
    93  			config: `source: wineventlog
    94  event_channel: Security
    95  event_level: Error
    96  event_ids:
    97   - 42
    98   - 43`,
    99  			expectedQuery: "<QueryList><Query><Select Path=\"Security\">*[System[(EventID=42 or EventID=43) and (Level=2)]]</Select></Query></QueryList>",
   100  			expectedErr:   "",
   101  		},
   102  		{
   103  			config: `source: wineventlog
   104  event_channel: Security`,
   105  			expectedQuery: "<QueryList><Query><Select Path=\"Security\">*</Select></Query></QueryList>",
   106  			expectedErr:   "",
   107  		},
   108  		{
   109  			config: `source: wineventlog
   110  event_channel: Security
   111  event_level: bla`,
   112  			expectedQuery: "",
   113  			expectedErr:   "invalid log level",
   114  		},
   115  	}
   116  	subLogger := log.WithFields(log.Fields{
   117  		"type": "windowseventlog",
   118  	})
   119  	for _, test := range tests {
   120  		f := WinEventLogSource{}
   121  		f.Configure([]byte(test.config), subLogger, configuration.METRICS_NONE)
   122  		q, err := f.buildXpathQuery()
   123  		if test.expectedErr != "" {
   124  			if err == nil {
   125  				t.Fatalf("expected error '%s' but got none", test.expectedErr)
   126  			}
   127  			assert.Contains(t, err.Error(), test.expectedErr)
   128  		} else {
   129  			require.NoError(t, err)
   130  			assert.Equal(t, test.expectedQuery, q)
   131  		}
   132  	}
   133  }
   134  
   135  func TestLiveAcquisition(t *testing.T) {
   136  	if runtime.GOOS != "windows" {
   137  		t.Skip("Skipping test on non-windows OS")
   138  	}
   139  
   140  	tests := []struct {
   141  		config        string
   142  		expectedLines []string
   143  	}{
   144  		{
   145  			config: `source: wineventlog
   146  xpath_query: |
   147   <QueryList>
   148     <Query Id="0" Path="Application">
   149       <Select Path="Application">*[System[(Level=4 or Level=0) and (EventID=42)]]</Select>
   150     </Query>
   151   </QueryList>`,
   152  			expectedLines: []string{
   153  				"blabla",
   154  				"test",
   155  				"aaaa",
   156  				"bbbbb",
   157  			},
   158  		},
   159  		{
   160  			config: `source: wineventlog
   161  xpath_query: |
   162   <sdf>asdfsdf`,
   163  			expectedLines: nil,
   164  		},
   165  		{
   166  			config: `source: wineventlog
   167  event_channel: Application
   168  event_level: Information
   169  event_ids:
   170   - 42`,
   171  			expectedLines: []string{
   172  				"testmessage",
   173  			},
   174  		},
   175  		{
   176  			config: `source: wineventlog
   177  event_channel: Application
   178  event_level: Information
   179  event_ids:
   180   - 43`,
   181  			expectedLines: nil,
   182  		},
   183  	}
   184  	subLogger := log.WithFields(log.Fields{
   185  		"type": "windowseventlog",
   186  	})
   187  
   188  	evthandler, err := eventlog.Open("Application")
   189  
   190  	if err != nil {
   191  		t.Fatalf("failed to open event log: %s", err)
   192  	}
   193  
   194  	for _, test := range tests {
   195  		to := &tomb.Tomb{}
   196  		c := make(chan types.Event)
   197  		f := WinEventLogSource{}
   198  		f.Configure([]byte(test.config), subLogger, configuration.METRICS_NONE)
   199  		f.StreamingAcquisition(c, to)
   200  		time.Sleep(time.Second)
   201  		lines := test.expectedLines
   202  		go func() {
   203  			for _, line := range lines {
   204  				evthandler.Info(42, line)
   205  			}
   206  		}()
   207  		ticker := time.NewTicker(time.Second * 5)
   208  		linesRead := make([]string, 0)
   209  	READLOOP:
   210  		for {
   211  			select {
   212  			case <-ticker.C:
   213  				if test.expectedLines == nil {
   214  					break READLOOP
   215  				}
   216  				t.Fatalf("timeout")
   217  			case e := <-c:
   218  				line, _ := exprhelpers.XMLGetNodeValue(e.Line.Raw, "/Event/EventData[1]/Data")
   219  				linesRead = append(linesRead, line.(string))
   220  				if len(linesRead) == len(lines) {
   221  					break READLOOP
   222  				}
   223  			}
   224  		}
   225  		if test.expectedLines == nil {
   226  			assert.Empty(t, linesRead)
   227  		} else {
   228  			assert.Equal(t, test.expectedLines, linesRead)
   229  		}
   230  		to.Kill(nil)
   231  		to.Wait()
   232  	}
   233  }