Skip to content

Commit

Permalink
[Auditbeat] Login dataset: Add event category and type (#11339)
Browse files Browse the repository at this point in the history
Adds `event.category: authentication` and `event.type: authentication_success` (or `authentication_failure`).
  • Loading branch information
Christoph Wurm authored Mar 22, 2019
1 parent 80c930c commit 09a8fa8
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 11 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.next.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d
- Add `entity_id` fields. {pull}10500[10500]
- Add seven dashboards for the system module. {pull}10511[10511]
- Move System module to beta. {pull}10800[10800]
- Login dataset: Add event category and type. {pull}11339[11339]

*Filebeat*

Expand Down
18 changes: 8 additions & 10 deletions x-pack/auditbeat/module/system/login/_meta/data.json
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
{
"@timestamp": "2017-10-12T08:05:34.853Z",
"agent": {
"hostname": "host.example.com",
"name": "host.example.com"
},
"event": {
"action": "user_login",
"category": "authentication",
"dataset": "login",
"kind": "event",
"module": "system",
"origin": "/var/log/wtmp.1",
"outcome": "success"
"origin": "/var/log/wtmp",
"outcome": "success",
"type": "authentication_success"
},
"message": "Login by user vagrant (UID: 1000) on pts/1 (PID: 17559) from 10.0.2.2 (IP: 10.0.2.2)",
"message": "Login by user vagrant (UID: 1000) on pts/2 (PID: 14962) from 10.0.2.2 (IP: 10.0.2.2)",
"process": {
"pid": 17559
"pid": 14962
},
"service": {
"type": "system"
Expand All @@ -25,6 +23,6 @@
"user": {
"id": 1000,
"name": "vagrant",
"terminal": "pts/1"
"terminal": "pts/2"
}
}
}
4 changes: 4 additions & 0 deletions x-pack/auditbeat/module/system/login/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,9 +202,13 @@ func (ms *MetricSet) loginEvent(loginRecord *LoginRecord) mb.Event {

switch loginRecord.Type {
case userLoginRecord:
event.RootFields.Put("event.category", "authentication")
event.RootFields.Put("event.outcome", "success")
event.RootFields.Put("event.type", "authentication_success")
case userLoginFailedRecord:
event.RootFields.Put("event.category", "authentication")
event.RootFields.Put("event.outcome", "failure")
event.RootFields.Put("event.type", "authentication_failure")
}

return event
Expand Down
51 changes: 50 additions & 1 deletion x-pack/auditbeat/module/system/login/login_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ func TestData(t *testing.T) {
config["login.wtmp_file_pattern"] = "../../../tests/files/wtmp"
config["login.btmp_file_pattern"] = ""
f := mbtest.NewReportingMetricSetV2(t, config)
defer f.(*MetricSet).utmpReader.bucket.DeleteBucket()

events, errs := mbtest.ReportingFetchV2(f)
if len(errs) > 0 {
Expand All @@ -43,11 +44,50 @@ func TestData(t *testing.T) {
t.Fatalf("only one event expected, got %d", len(events))
}

events[0].RootFields.Put("event.origin", "/var/log/wtmp")
fullEvent := mbtest.StandardizeEvent(f, events[0], core.AddDatasetToEvent)
mbtest.WriteEventToDataJSON(t, fullEvent, "")
}

func TestFailedLogins(t *testing.T) {
func TestWtmp(t *testing.T) {
if byteOrder != binary.LittleEndian {
t.Skip("Test only works on little-endian systems - skipping.")
}

defer abtest.SetupDataDir(t)()

config := getBaseConfig()
config["login.wtmp_file_pattern"] = "../../../tests/files/wtmp"
config["login.btmp_file_pattern"] = ""
f := mbtest.NewReportingMetricSetV2(t, config)
defer f.(*MetricSet).utmpReader.bucket.DeleteBucket()

events, errs := mbtest.ReportingFetchV2(f)
if len(errs) > 0 {
t.Fatalf("received error: %+v", errs[0])
}

if len(events) == 0 {
t.Fatal("no events were generated")
} else if len(events) != 1 {
t.Fatalf("only one event expected, got %d", len(events))
}

// utmpdump: [7] [14962] [ts/2] [vagrant ] [pts/2 ] [10.0.2.2 ] [10.0.2.2 ] [2019-01-24T09:51:51,367964+00:00]
checkFieldValue(t, events[0].RootFields, "event.kind", "event")
checkFieldValue(t, events[0].RootFields, "event.category", "authentication")
checkFieldValue(t, events[0].RootFields, "event.action", "user_login")
checkFieldValue(t, events[0].RootFields, "event.outcome", "success")
checkFieldValue(t, events[0].RootFields, "event.type", "authentication_success")
checkFieldValue(t, events[0].RootFields, "process.pid", 14962)
checkFieldValue(t, events[0].RootFields, "source.ip", "10.0.2.2")
checkFieldValue(t, events[0].RootFields, "user.name", "vagrant")
checkFieldValue(t, events[0].RootFields, "user.terminal", "pts/2")
assert.True(t, events[0].Timestamp.Equal(time.Date(2019, 1, 24, 9, 51, 51, 367964000, time.UTC)),
"Timestamp is not equal: %+v", events[0].Timestamp)
}

func TestBtmp(t *testing.T) {
if byteOrder != binary.LittleEndian {
t.Skip("Test only works on little-endian systems - skipping.")
}
Expand All @@ -58,6 +98,7 @@ func TestFailedLogins(t *testing.T) {
config["login.wtmp_file_pattern"] = ""
config["login.btmp_file_pattern"] = "../../../tests/files/btmp_ubuntu1804"
f := mbtest.NewReportingMetricSetV2(t, config)
defer f.(*MetricSet).utmpReader.bucket.DeleteBucket()

events, errs := mbtest.ReportingFetchV2(f)
if len(errs) > 0 {
Expand All @@ -72,8 +113,10 @@ func TestFailedLogins(t *testing.T) {

// utmpdump: [6] [03307] [ ] [root ] [ssh:notty ] [10.0.2.2 ] [10.0.2.2 ] [2019-02-20T17:42:26,000000+0000]
checkFieldValue(t, events[0].RootFields, "event.kind", "event")
checkFieldValue(t, events[0].RootFields, "event.category", "authentication")
checkFieldValue(t, events[0].RootFields, "event.action", "user_login")
checkFieldValue(t, events[0].RootFields, "event.outcome", "failure")
checkFieldValue(t, events[0].RootFields, "event.type", "authentication_failure")
checkFieldValue(t, events[0].RootFields, "process.pid", 3307)
checkFieldValue(t, events[0].RootFields, "source.ip", "10.0.2.2")
checkFieldValue(t, events[0].RootFields, "user.id", 0)
Expand All @@ -85,8 +128,10 @@ func TestFailedLogins(t *testing.T) {
// The second UTMP entry in the btmp test file is a duplicate of the first, this is what Ubuntu 18.04 generates.
// utmpdump: [6] [03307] [ ] [root ] [ssh:notty ] [10.0.2.2 ] [10.0.2.2 ] [2019-02-20T17:42:26,000000+0000]
checkFieldValue(t, events[1].RootFields, "event.kind", "event")
checkFieldValue(t, events[0].RootFields, "event.category", "authentication")
checkFieldValue(t, events[1].RootFields, "event.action", "user_login")
checkFieldValue(t, events[1].RootFields, "event.outcome", "failure")
checkFieldValue(t, events[0].RootFields, "event.type", "authentication_failure")
checkFieldValue(t, events[1].RootFields, "process.pid", 3307)
checkFieldValue(t, events[1].RootFields, "source.ip", "10.0.2.2")
checkFieldValue(t, events[1].RootFields, "user.id", 0)
Expand All @@ -97,8 +142,10 @@ func TestFailedLogins(t *testing.T) {

// utmpdump: [7] [03788] [/0 ] [elastic ] [pts/0 ] [ ] [0.0.0.0 ] [2019-02-20T17:45:08,447344+0000]
checkFieldValue(t, events[2].RootFields, "event.kind", "event")
checkFieldValue(t, events[0].RootFields, "event.category", "authentication")
checkFieldValue(t, events[2].RootFields, "event.action", "user_login")
checkFieldValue(t, events[2].RootFields, "event.outcome", "failure")
checkFieldValue(t, events[0].RootFields, "event.type", "authentication_failure")
checkFieldValue(t, events[2].RootFields, "process.pid", 3788)
checkFieldValue(t, events[2].RootFields, "source.ip", "0.0.0.0")
checkFieldValue(t, events[2].RootFields, "user.name", "elastic")
Expand All @@ -108,8 +155,10 @@ func TestFailedLogins(t *testing.T) {

// utmpdump: [7] [03788] [/0 ] [UNKNOWN ] [pts/0 ] [ ] [0.0.0.0 ] [2019-02-20T17:45:15,765318+0000]
checkFieldValue(t, events[3].RootFields, "event.kind", "event")
checkFieldValue(t, events[0].RootFields, "event.category", "authentication")
checkFieldValue(t, events[3].RootFields, "event.action", "user_login")
checkFieldValue(t, events[3].RootFields, "event.outcome", "failure")
checkFieldValue(t, events[0].RootFields, "event.type", "authentication_failure")
checkFieldValue(t, events[3].RootFields, "process.pid", 3788)
checkFieldValue(t, events[3].RootFields, "source.ip", "0.0.0.0")
contains, err := events[3].RootFields.HasKey("user.id")
Expand Down

0 comments on commit 09a8fa8

Please sign in to comment.