Description
After reviewing proposals and discussions, new and old, private and public (#117, #234, #589, #678, elastic/beats#9963, elastic/beats#10111, elastic/beats#10192), here's a high level proposal. I'd like to get feedback on this.
When user.*
is populated at the root of an event, it's meant to capture the user performing an action, or the only user relevant to an event, when that's the situation.
The goal of this proposal is to solve the following use cases:
- User A creates or deletes User B (no prior or post state)
- User A modifies User B (there's a prior and a post state)
- User A assumes the identity of User B (or fails to)
One thing to note, is that with real-time privilege escalation (e.g. sudo, MacOS modal) or auditing frameworks like auditd, it's useful to be able to identify all 3 of these additional users concurrently, in a single event.
Here are locations I propose we could nest the user schema, to represent various use cases:
- user.effective.*
- user.target.*
- user.new.*
Note that in each of these cases, we are nesting the user
schema as a new name, similar to what we do with process.parent
. To give a concrete example the effective user name would be at user.effective.name
(not at user.effective.user.name
).
user.effective.*
Used to identify the final identity, when logging in remotely as another user, or escalating privileges.
Simplified privilege escalation example, where "alice" escalates privileges to "root":
{
"user": {
"name": "alice",
"effective": {
"name": "root"
}
}
}
user.target.*
Used to identify the user being modified, or targeted by an action.
Simplified user management example, where "root" modifies user "bob":
{
"user": {
"name": "root",
"target": {
"name": "bob"
}
}
}
user.new.*
Used to identify what was changed about the user. Ideally this would only capture the difference, not repeat all values.
Simplified user management example, when an existing user is modified, for example changing user name. Here user "bob" is renamed "foo" by "root":
{
"user": {
"name": "root",
"target": {
"name": "bob"
},
"new": {
"name": "foo"
}
}
}
Note: The creation of a new user would only use user.target
, not user.new
. user.new
should only be used.
Putting it all together
If it's possible to determine who was the original user prior to privilege escalation, a full event could look like this:
{
"user": {
"name": "alice",
"effective": {
"name": "root"
},
"target": {
"name": "bob"
}
}
}
The action being observed should be captured in event.action
.
If the event is user management, the category fields should be event.category: [ "iam" ]
and event.type: [ "user" ]
with a secondary entry in event.type
, whichever is more appropriate: "creation", "deletion" or "change".
If the event is authentication and privilege escalation, event.category: [ "authentication" ]
, event.type: ["start"]
and event.outcome
either "success" or "failure".
Discussion points
Nowhere in the above plan do we use the current nestings of the user
field set: client.user
, destination.user
, host.user
, server.user
, source.user
.
I'm wondering if people are using host.user
or if we should deprecate it for removal in ECS 2.0.
I'd also like to know if the 4 nestings under the network-related field sets are currently being used. I realize that folks may have used for example source.user
and destination.user
to model remote logons or the "acting" vs "target" users, with ECS specifying nothing yet on how these interactions should be modelled until now. I'd like to get your input if the plan above makes sense.
Are there other uses that are actually network-related for source.user
and destination.user
?