@@ -8,17 +8,19 @@ package login
88
99import (
1010 "encoding/binary"
11+ "io"
1112 "io/ioutil"
1213 "net"
1314 "os"
15+ "path/filepath"
1416 "testing"
1517 "time"
1618
1719 "github.com/stretchr/testify/assert"
1820
1921 "github.com/elastic/beats/auditbeat/core"
22+ abtest "github.com/elastic/beats/auditbeat/testing"
2023 "github.com/elastic/beats/libbeat/common"
21- "github.com/elastic/beats/libbeat/paths"
2224 mbtest "github.com/elastic/beats/metricbeat/mb/testing"
2325)
2426
@@ -27,12 +29,13 @@ func TestData(t *testing.T) {
2729 t .Skip ("Test only works on little-endian systems - skipping." )
2830 }
2931
30- defer setup (t )()
32+ defer abtest . SetupDataDir (t )()
3133
3234 config := getBaseConfig ()
33- config ["login.wtmp_file_pattern" ] = "../../../tests/files /wtmp"
35+ config ["login.wtmp_file_pattern" ] = "./testdata /wtmp"
3436 config ["login.btmp_file_pattern" ] = ""
3537 f := mbtest .NewReportingMetricSetV2 (t , config )
38+ defer f .(* MetricSet ).utmpReader .bucket .DeleteBucket ()
3639
3740 events , errs := mbtest .ReportingFetchV2 (f )
3841 if len (errs ) > 0 {
@@ -45,21 +48,98 @@ func TestData(t *testing.T) {
4548 t .Fatalf ("only one event expected, got %d" , len (events ))
4649 }
4750
51+ events [0 ].RootFields .Put ("event.origin" , "/var/log/wtmp" )
4852 fullEvent := mbtest .StandardizeEvent (f , events [0 ], core .AddDatasetToEvent )
4953 mbtest .WriteEventToDataJSON (t , fullEvent , "" )
5054}
5155
52- func TestFailedLogins (t * testing.T ) {
56+ func TestWtmp (t * testing.T ) {
5357 if byteOrder != binary .LittleEndian {
5458 t .Skip ("Test only works on little-endian systems - skipping." )
5559 }
5660
57- defer setup (t )()
61+ defer abtest .SetupDataDir (t )()
62+
63+ dir := setupTestDir (t )
64+ defer os .RemoveAll (dir )
65+
66+ wtmpFilepath := filepath .Join (dir , "wtmp" )
67+
68+ config := getBaseConfig ()
69+ config ["login.wtmp_file_pattern" ] = wtmpFilepath
70+ config ["login.btmp_file_pattern" ] = ""
71+ f := mbtest .NewReportingMetricSetV2 (t , config )
72+ defer f .(* MetricSet ).utmpReader .bucket .DeleteBucket ()
73+
74+ events , errs := mbtest .ReportingFetchV2 (f )
75+ if len (errs ) > 0 {
76+ t .Fatalf ("received error: %+v" , errs [0 ])
77+ }
78+
79+ if len (events ) == 0 {
80+ t .Fatal ("no events were generated" )
81+ } else if len (events ) != 1 {
82+ t .Fatalf ("only one event expected, got %d" , len (events ))
83+ }
84+
85+ // utmpdump: [7] [14962] [ts/2] [vagrant ] [pts/2 ] [10.0.2.2 ] [10.0.2.2 ] [2019-01-24T09:51:51,367964+00:00]
86+ checkFieldValue (t , events [0 ].RootFields , "event.kind" , "event" )
87+ checkFieldValue (t , events [0 ].RootFields , "event.action" , "user_login" )
88+ checkFieldValue (t , events [0 ].RootFields , "event.outcome" , "success" )
89+ checkFieldValue (t , events [0 ].RootFields , "process.pid" , 14962 )
90+ checkFieldValue (t , events [0 ].RootFields , "source.ip" , "10.0.2.2" )
91+ checkFieldValue (t , events [0 ].RootFields , "user.name" , "vagrant" )
92+ checkFieldValue (t , events [0 ].RootFields , "user.terminal" , "pts/2" )
93+ assert .True (t , events [0 ].Timestamp .Equal (time .Date (2019 , 1 , 24 , 9 , 51 , 51 , 367964000 , time .UTC )),
94+ "Timestamp is not equal: %+v" , events [0 ].Timestamp )
95+
96+ // Append logout event to wtmp file and check that it's read
97+ wtmpFile , err := os .OpenFile (wtmpFilepath , os .O_APPEND | os .O_WRONLY , 0644 )
98+ if err != nil {
99+ t .Fatalf ("error opening %v: %v" , wtmpFilepath , err )
100+ }
101+
102+ loginUtmp := utmpC {
103+ Type : DEAD_PROCESS ,
104+ }
105+ copy (loginUtmp .Device [:], "pts/2" )
106+
107+ err = binary .Write (wtmpFile , byteOrder , loginUtmp )
108+ if err != nil {
109+ t .Fatalf ("error writing to %v: %v" , wtmpFilepath , err )
110+ }
111+
112+ events , errs = mbtest .ReportingFetchV2 (f )
113+ if len (errs ) > 0 {
114+ t .Fatalf ("received error: %+v" , errs [0 ])
115+ }
116+
117+ if len (events ) == 0 {
118+ t .Fatal ("no events were generated" )
119+ } else if len (events ) != 1 {
120+ t .Fatalf ("only one event expected, got %d: %v" , len (events ), events )
121+ }
122+
123+ checkFieldValue (t , events [0 ].RootFields , "event.kind" , "event" )
124+ checkFieldValue (t , events [0 ].RootFields , "event.action" , "user_logout" )
125+ checkFieldValue (t , events [0 ].RootFields , "process.pid" , 14962 )
126+ checkFieldValue (t , events [0 ].RootFields , "source.ip" , "10.0.2.2" )
127+ checkFieldValue (t , events [0 ].RootFields , "user.name" , "vagrant" )
128+ checkFieldValue (t , events [0 ].RootFields , "user.terminal" , "pts/2" )
129+ }
130+
131+ func TestBtmp (t * testing.T ) {
132+ if byteOrder != binary .LittleEndian {
133+ t .Skip ("Test only works on little-endian systems - skipping." )
134+ }
135+
136+ defer abtest .SetupDataDir (t )()
58137
59138 config := getBaseConfig ()
60139 config ["login.wtmp_file_pattern" ] = ""
61- config ["login.btmp_file_pattern" ] = "../../../tests/files/btmp_ubuntu1804 "
140+ config ["login.btmp_file_pattern" ] = "./testdata/btmp* "
62141 f := mbtest .NewReportingMetricSetV2 (t , config )
142+ defer f .(* MetricSet ).utmpReader .bucket .DeleteBucket ()
63143
64144 events , errs := mbtest .ReportingFetchV2 (f )
65145 if len (errs ) > 0 {
@@ -144,14 +224,47 @@ func getBaseConfig() map[string]interface{} {
144224 }
145225}
146226
147- // setup is copied from file_integrity/metricset_test.go.
148- // TODO: Move to shared location and use in all unit tests.
149- func setup (t testing.TB ) func () {
150- // path.data should be set so that the DB is written to a predictable location.
151- var err error
152- paths .Paths .Data , err = ioutil .TempDir ("" , "beat-data-dir" )
227+ // setupTestDir creates a temporary directory, copies the test files into it,
228+ // and returns the path.
229+ func setupTestDir (t * testing.T ) string {
230+ tmp , err := ioutil .TempDir ("" , "auditbeat-login-test-dir" )
231+ if err != nil {
232+ t .Fatal ("failed to create temp dir" )
233+ }
234+
235+ copyDir (t , "./testdata" , tmp )
236+
237+ return tmp
238+ }
239+
240+ func copyDir (t * testing.T , src , dst string ) {
241+ files , err := ioutil .ReadDir (src )
242+ if err != nil {
243+ t .Fatalf ("failed to read %v" , src )
244+ }
245+
246+ for _ , file := range files {
247+ srcFile := filepath .Join (src , file .Name ())
248+ dstFile := filepath .Join (dst , file .Name ())
249+ copyFile (t , srcFile , dstFile )
250+ }
251+ }
252+
253+ func copyFile (t * testing.T , src , dst string ) {
254+ in , err := os .Open (src )
255+ if err != nil {
256+ t .Fatalf ("failed to open %v" , src )
257+ }
258+ defer in .Close ()
259+
260+ out , err := os .Create (dst )
261+ if err != nil {
262+ t .Fatalf ("failed to open %v" , dst )
263+ }
264+ defer out .Close ()
265+
266+ _ , err = io .Copy (out , in )
153267 if err != nil {
154- t .Fatal ( )
268+ t .Fatalf ( "failed to copy %v to %v" , src , dst )
155269 }
156- return func () { os .RemoveAll (paths .Paths .Data ) }
157270}
0 commit comments