App-Spoor
view release on metacpan or search on metacpan
lib/App/Spoor/LoginEntryParser.pm view on Meta::CPAN
package App::Spoor::LoginEntryParser;
use v5.10;
use strict;
use warnings;
=head1 NAME
App::Spoor::LoginEntryParser
=head1 VERSION
Version 0.01
=cut
our $VERSION = '0.01';
=head1 SYNOPSIS
This package contains the necessary functionality to parse CPanel error log entries.
=head1 SUBROUTINES/METHODS
=head2 parse
This subroutine accepts a single line from a CPanel login log (as a string) and returns a reference to a hash
representation of that entry.
The hash representation contains the following elements:
=over 2
=item * type: This is hardcoded to 'login'
=item * event: This is hardcoded to 'login'.
=item * log_time: A DateTime instance representing the time of the log entry.
=item * context: The context within which the operation is being performed can be either 'mailbox', 'domain' or 'system'.
=item * scope: Can be one of 'webmaild', 'cpaneld' or 'whostmgrd'.
=item * ip: The ip logging in.
=item * status: Can be one of 'success', 'deferred' or 'failed'.
=item * credential: The credential (email address/username) presented.
=item * possessor: In the case of an email address being provided, the domain user to which it belongs.
=item * message: This is only set if the entry contained additional info (generally on a non-successful login), e.g. "security token missing".
=item * endpoint: HTTP-related information, only present on a non-successful login.
=back
=cut
sub parse {
use DateTime::Format::Strptime;
my $log_entry = shift;
my $date_parser = DateTime::Format::Strptime->new(pattern => '%Y-%m-%d %H:%M:%S %z', on_error => 'croak');
my %response;
if ($log_entry =~ /
\A
\[(?<timestamp>[^\]]+)\]\s
info\s
\[(?<scope>[^\]]+)\]\s
(?<ip>\S+)\s
-\s(?<credential_string>[^-]+)\s-\s
SUCCESS
/x) {
%response = (
type => 'login',
event => 'login',
log_time => $date_parser->parse_datetime($+{timestamp})->epoch(),
scope => $+{scope},
ip => $+{ip},
status => 'success',
);
if ($+{credential_string} =~ /\A(?<credential>\S+)\s\(possessor: (?<possessor>[^\)]+)\)/) {
$response{credential} = $+{credential};
$response{possessor} = $+{possessor};
} else {
$response{credential} = $+{credential_string};
}
} elsif ($log_entry =~ /
\A
\[(?<timestamp>[^\]]+)\]\s
info\s
\[(?<scope>[^\]]+)\]\s
(?<ip>\S+)\s
-\s(?<credential>[^-]+)\s
"(?<endpoint>[^"]+)"\s
(?<status>[A-Z]+)\s
[^:]+:\s(?<message>.+)
\Z
/x) {
%response = (
type => 'login',
event => 'login',
log_time => $date_parser->parse_datetime($+{timestamp})->epoch(),
scope => $+{scope},
ip => $+{ip},
status => lc($+{status}),
credential => $+{credential},
message => $+{message},
endpoint => $+{endpoint}
);
}
if ($response{scope} eq 'webmaild' && $response{credential} =~ /@/) {
$response{context} = 'mailbox';
} elsif ($response{scope} eq 'webmaild') {
$response{context} = 'domain';
} elsif ($response{scope} eq 'cpaneld') {
$response{context} = 'domain';
} elsif ($response{scope} eq 'whostmgrd') {
$response{context} = 'system';
}
( run in 0.946 second using v1.01-cache-2.11-cpan-d8267643d1d )