Replace userLogger with a more flexible system
Current situation
Currently, events are logged by the userLogger system, with the same semantic as technical logs:
Code:
$self->userLogger->notice( 'User '
. $ref->{ $self->conf->{whatToTrace} }
. " successfully authenticated at level $ref->{authenticationLevel}"
);
Result:
[notice] User dwho successfully authenticated at level 2
This system has limitations:
- Not enough information (ip address? authentication method? etc)
- Hard to parse for analysis tools (
/User (.+) successfully authenticated at level (\d+)/
) - Fragile: if the error message changes sysadmins have to reconfigure their logging system
- Difficult to integrate to a third party system (storing events to a db, redis, or sending them to a security tool)
- There is no central list of all possible events
- Do levels even make sense? What is the difference between
userLogger->notice
anduserLogger->error
? They are both events.
Proposal
I would like to replace userLogger with a more flexible system, for example by passing a hash with contextual data:
Code:
$self->auditLog($req,
event_code => "USER_AUTHENTICATED",
level => $ref->{authenticationLevel},
user_id => $ref->{ $self->conf->{whatToTrace});
);
What happens then could be completely delegated to a plugin, for example, one plugin could construct a template from the event_code
:
"USER_AUTHENTICATED": "User $user_id successfully authenticated at level $level from IP $req->ipaddr"
and render it as:
User dwho successfully authenticated at level 2 from IP 127.0.0.1
Another plugin could simply log:
USER_AUTHENTICATED: user_id=dwho, level=2, ip=127.0.0.1
Another plugin could save the data into Redis, etc.
Roadmap
I am hoping to have this feature sponsored and integrated into the 2.X branch, which means we have to preserve compatibility. In order to do this:
- We need to modify all $self->userLogger calls to use the new system in the existing code base
- The default configuration of the new system must match the old error messages, so that existing log parsing tools are not broken (this can be done by shipping a plugin that maps event codes to the previously logged string)
- For people who use userLogger in third-party plugins, we need to povide a userLogger adapter that plugs into the new system, like this:
sub error {
my ($message) = @_;
$self->auditLog( level => "error", message => $message );
}