From 7d7d951ec8260761d763495a8e55bccc48bf0dc9 Mon Sep 17 00:00:00 2001 From: Andrew Stucki Date: Mon, 27 Apr 2020 23:48:57 -0400 Subject: [PATCH 1/5] [Auditbeat] Add system module user dataset ECS categorization fields --- x-pack/auditbeat/module/system/user/user.go | 23 +++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/x-pack/auditbeat/module/system/user/user.go b/x-pack/auditbeat/module/system/user/user.go index ffa4e272b83..eb0bfa79084 100644 --- a/x-pack/auditbeat/module/system/user/user.go +++ b/x-pack/auditbeat/module/system/user/user.go @@ -76,6 +76,23 @@ func (action eventAction) String() string { } } +func (action eventAction) Type() string { + switch action { + case eventActionExistingUser: + return "info" + case eventActionUserAdded: + return "creation" + case eventActionUserRemoved: + return "deletion" + case eventActionUserChanged: + return "change" + case eventActionPasswordChanged: + return "change" + default: + return "info" + } +} + type passwordType uint8 const ( @@ -430,8 +447,10 @@ func (ms *MetricSet) userEvent(user *User, eventType string, action eventAction) event := mb.Event{ RootFields: common.MapStr{ "event": common.MapStr{ - "kind": eventType, - "action": action.String(), + "kind": eventType, + "category": []string{"iam"}, + "type": []string{action.Type()}, + "action": action.String(), }, "user": common.MapStr{ "id": user.UID, From 784f86f0290d5e6efc3e9f93a2abc907d59571a5 Mon Sep 17 00:00:00 2001 From: Andrew Stucki Date: Mon, 27 Apr 2020 23:51:30 -0400 Subject: [PATCH 2/5] add changelog entry --- CHANGELOG.next.asciidoc | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.next.asciidoc b/CHANGELOG.next.asciidoc index b1f70eea949..fde7600fcb3 100644 --- a/CHANGELOG.next.asciidoc +++ b/CHANGELOG.next.asciidoc @@ -210,6 +210,7 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d - Log to stderr when running using reference kubernetes manifests. {pull}17443[174443] - Fix syscall kprobe arguments for 32-bit systems in socket module. {pull}17500[17500] - Fix memory leak on when we miss socket close kprobe events. {pull}17500[17500] +- Add system module user dataset ECS categorization fields. {pull}18035[18035] *Filebeat* From f05dbd6fd29aff560772b6c85e374b305d44ca3c Mon Sep 17 00:00:00 2001 From: Andrew Stucki Date: Tue, 5 May 2020 00:01:17 -0400 Subject: [PATCH 3/5] Add user.group and related.user fields --- x-pack/auditbeat/module/system/user/user.go | 25 +++++++++++++++++++ .../auditbeat/module/system/user/user_test.go | 11 ++++++++ 2 files changed, 36 insertions(+) diff --git a/x-pack/auditbeat/module/system/user/user.go b/x-pack/auditbeat/module/system/user/user.go index eb0bfa79084..59f23e566e8 100644 --- a/x-pack/auditbeat/module/system/user/user.go +++ b/x-pack/auditbeat/module/system/user/user.go @@ -181,6 +181,7 @@ func (user User) toMapStr() common.MapStr { groupMapStr = append(groupMapStr, common.MapStr{ "name": group.Name, "gid": group.Gid, + "id": group.Gid, }) } evt.Put("group", groupMapStr) @@ -189,6 +190,15 @@ func (user User) toMapStr() common.MapStr { return evt } +func (user User) PrimaryGroup() *user.Group { + for _, group := range user.Groups { + if group.Gid == user.GID { + return group + } + } + return nil +} + // entityID creates an ID that uniquely identifies this user across machines. func (u User) entityID(hostID string) string { h := system.NewEntityHash() @@ -456,6 +466,9 @@ func (ms *MetricSet) userEvent(user *User, eventType string, action eventAction) "id": user.UID, "name": user.Name, }, + "related": common.MapStr{ + "user": []string{user.Name}, + }, "message": userMessage(user, action), }, MetricSetFields: user.toMapStr(), @@ -465,6 +478,18 @@ func (ms *MetricSet) userEvent(user *User, eventType string, action eventAction) event.RootFields.Put("user.entity_id", user.entityID(ms.HostID())) } + primaryGroup := user.PrimaryGroup() + if primaryGroup != nil { + event.RootFields.Put("user.group", common.MapStr{ + "id": primaryGroup.Gid, + "name": primaryGroup.Name, + }) + } else if user.GID != "" { // fallback to just filling out the GID + event.RootFields.Put("user.group", common.MapStr{ + "id": user.GID, + }) + } + return event } diff --git a/x-pack/auditbeat/module/system/user/user_test.go b/x-pack/auditbeat/module/system/user/user_test.go index 14708232d29..a56a53f9eb4 100644 --- a/x-pack/auditbeat/module/system/user/user_test.go +++ b/x-pack/auditbeat/module/system/user/user_test.go @@ -11,6 +11,8 @@ import ( "testing" "time" + "github.com/stretchr/testify/require" + "github.com/elastic/beats/v7/auditbeat/core" abtest "github.com/elastic/beats/v7/auditbeat/testing" mbtest "github.com/elastic/beats/v7/metricbeat/mb/testing" @@ -37,6 +39,15 @@ func TestData(t *testing.T) { for _, e := range events { if name, _ := e.RootFields.GetValue("user.name"); name == "elastic" { + relatedNames, err := e.RootFields.GetValue("related.user") + require.NoError(t, err) + require.Equal(t, []string{"elastic"}, relatedNames) + groupName, err := e.RootFields.GetValue("user.group.name") + require.NoError(t, err) + require.Equal(t, "elastic", groupName) + groupID, err := e.RootFields.GetValue("user.group.id") + require.NoError(t, err) + require.Equal(t, "1001", groupID) fullEvent := mbtest.StandardizeEvent(f, e, core.AddDatasetToEvent) mbtest.WriteEventToDataJSON(t, fullEvent, "") return From e9eb7d0cccc16209ff861272720fbc8bde25cf6f Mon Sep 17 00:00:00 2001 From: Andrew Stucki Date: Tue, 5 May 2020 02:32:28 -0400 Subject: [PATCH 4/5] Remove group name that may not match across test environments --- x-pack/auditbeat/module/system/user/user_test.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/x-pack/auditbeat/module/system/user/user_test.go b/x-pack/auditbeat/module/system/user/user_test.go index a56a53f9eb4..a3c30906f39 100644 --- a/x-pack/auditbeat/module/system/user/user_test.go +++ b/x-pack/auditbeat/module/system/user/user_test.go @@ -42,9 +42,6 @@ func TestData(t *testing.T) { relatedNames, err := e.RootFields.GetValue("related.user") require.NoError(t, err) require.Equal(t, []string{"elastic"}, relatedNames) - groupName, err := e.RootFields.GetValue("user.group.name") - require.NoError(t, err) - require.Equal(t, "elastic", groupName) groupID, err := e.RootFields.GetValue("user.group.id") require.NoError(t, err) require.Equal(t, "1001", groupID) From 03008d067d3bbc3bb28507f6243bd78eecbe03ed Mon Sep 17 00:00:00 2001 From: Andrew Stucki Date: Tue, 5 May 2020 09:24:26 -0400 Subject: [PATCH 5/5] Modify test so it doesn't pick up real user events --- x-pack/auditbeat/module/system/user/user_test.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/x-pack/auditbeat/module/system/user/user_test.go b/x-pack/auditbeat/module/system/user/user_test.go index a3c30906f39..a8fd6f85238 100644 --- a/x-pack/auditbeat/module/system/user/user_test.go +++ b/x-pack/auditbeat/module/system/user/user_test.go @@ -38,10 +38,13 @@ func TestData(t *testing.T) { } for _, e := range events { - if name, _ := e.RootFields.GetValue("user.name"); name == "elastic" { + if name, _ := e.RootFields.GetValue("user.name"); name == "__elastic" { relatedNames, err := e.RootFields.GetValue("related.user") require.NoError(t, err) - require.Equal(t, []string{"elastic"}, relatedNames) + require.Equal(t, []string{"__elastic"}, relatedNames) + groupName, err := e.RootFields.GetValue("user.group.name") + require.NoError(t, err) + require.Equal(t, "__elastic", groupName) groupID, err := e.RootFields.GetValue("user.group.id") require.NoError(t, err) require.Equal(t, "1001", groupID) @@ -56,13 +59,13 @@ func TestData(t *testing.T) { func testUser() *User { return &User{ - Name: "elastic", + Name: "__elastic", UID: "9999", GID: "1001", Groups: []*user.Group{ &user.Group{ Gid: "1001", - Name: "elastic", + Name: "__elastic", }, &user.Group{ Gid: "1002",