10 |
rodolico |
1 |
#! /usr/bin/env perl
|
|
|
2 |
|
|
|
3 |
# script to process samba audit log, storing summary of information
|
|
|
4 |
# for future processing.
|
|
|
5 |
# will read $summaryFile into memory, if it exists, then scan
|
|
|
6 |
# $auditFile, adding new entries.
|
|
|
7 |
# will then write results back to $summaryFile (making a backup first)
|
|
|
8 |
# resulting file is a tab delimited text file, where each line begins
|
|
|
9 |
# with three standard fields; username, timestamp and IP.
|
|
|
10 |
# the remaining fields are actions based on %headers below (other actions
|
|
|
11 |
# are ignored).
|
|
|
12 |
#
|
|
|
13 |
# NOTE: timestamp is floor'd to the nearest day, ie int(timestamp/86400)*86400
|
|
|
14 |
# as we want to summarize a days activity.
|
|
|
15 |
|
|
|
16 |
use strict;
|
|
|
17 |
use warnings;
|
|
|
18 |
use Parse::Syslog;
|
|
|
19 |
# apt-get install libparse-syslog-perl
|
|
|
20 |
|
|
|
21 |
# path to Samba audit file
|
|
|
22 |
my $auditFile = '/var/log/samba/audit.log.1';
|
|
|
23 |
|
|
|
24 |
# path to our historical summary file
|
|
|
25 |
my $summaryFile = '/opt/sambaAudit/samba_audit.summary';
|
|
|
26 |
# hash to store all our activity
|
|
|
27 |
my %activity;
|
|
|
28 |
# hash containing the action headers we care about
|
|
|
29 |
my %headers = ( 'mkdir' => 1, 'pread' => 1, 'pwrite' => 1,'rmdir' => 1,'unlink' => 1 );
|
|
|
30 |
# number of seconds in a day, 86400. BREAKS on Daylight Savings Time
|
|
|
31 |
my $secondsInDay = 60*60*24;
|
|
|
32 |
|
|
|
33 |
# function loads the summary file into %activity
|
|
|
34 |
# also modified %headers, based on the headers it finds in the summary file
|
|
|
35 |
sub loadSummary {
|
|
|
36 |
open SUMMARY,"<$summaryFile" or return;
|
|
|
37 |
#print STDERR "Loading summary file\n";
|
|
|
38 |
# file exists, so read in the first line, which is the headers
|
|
|
39 |
my $line = <SUMMARY>;
|
|
|
40 |
chomp $line;
|
|
|
41 |
my @headers = split( "\t", $line );
|
|
|
42 |
# replace our preset ones with whatever headers we have here
|
|
|
43 |
%headers = map{ $_ => 1 } @headers;
|
|
|
44 |
# the following are not actions, so remove them from the headers
|
|
|
45 |
delete @headers{qw(user day ip)};
|
|
|
46 |
# read each line and create the activity.
|
|
|
47 |
# note that user, timestamp and IP are required to be in the first
|
|
|
48 |
# three columns
|
|
|
49 |
while ( $line = <SUMMARY> ) {
|
|
|
50 |
chomp $line;
|
|
|
51 |
my @data = split( "\t", $line );
|
|
|
52 |
for ( my $i = 3; $i < @headers; $i++ ) {
|
|
|
53 |
$activity{$data[0]}{$data[1]}{$data[2]}{$headers[$i]} = $data[$i];
|
|
|
54 |
}
|
|
|
55 |
}
|
|
|
56 |
close SUMMARY;
|
|
|
57 |
}
|
|
|
58 |
|
|
|
59 |
sub mailLog {
|
|
|
60 |
my $from = 'rodo@dailydata.net';
|
|
|
61 |
my $to = 'rodo@dailydata.net';
|
|
|
62 |
my $server = 'smtp.dailydata.net:587';
|
|
|
63 |
my $smtpuser = 'rodo@dailydata.net';
|
|
|
64 |
my $smtppass = 'naught/nice3';
|
|
|
65 |
`/opt/sendEmail/sendEmail.pl -f '$from' -t '$to' -u 'Samba Audit Log' -s 'smtp.dailydata.net:587' -a /opt/sambaAudit/samba_audit.summary -xu '$smtpuser' -xp '$smtppass' -l /tmp/sendemail.log -m 'Attached is the tab delimited file from the audit log'`;
|
|
|
66 |
}
|
|
|
67 |
|
|
|
68 |
# get our summary file into the access hash
|
|
|
69 |
&loadSummary();
|
|
|
70 |
|
|
|
71 |
# use Parse::Syslog to read in each line, mainly to get the timestamp
|
|
|
72 |
my $parser = Parse::Syslog->new( $auditFile );
|
|
|
73 |
while ( my $sl = $parser->next ) {
|
|
|
74 |
# remove the time from it; just date
|
|
|
75 |
my $timestamp = int( $sl->{'timestamp'} / $secondsInDay ) * $secondsInDay;
|
|
|
76 |
# text contains the information we care about
|
|
|
77 |
my @temp = split( '\|', $sl->{'text'} );
|
|
|
78 |
# and we only care about the first three of them, which are user, ip
|
|
|
79 |
# and the action they took
|
|
|
80 |
my ( $user, $ip, $action ) = @temp[0..2];
|
|
|
81 |
# update %activity if this is an action we track
|
|
|
82 |
$activity{$user}{$timestamp}{$ip}{$action}++ if $headers{$action};
|
|
|
83 |
}
|
|
|
84 |
|
|
|
85 |
# make a backup of the summary file, if it exists
|
|
|
86 |
unlink "$summaryFile~" if -e "$summaryFile~";
|
|
|
87 |
rename $summaryFile, "$summaryFile~" if -e $summaryFile;
|
|
|
88 |
# and overwrite it
|
|
|
89 |
open SUMMARY, ">$summaryFile" or die "Could not save summary file $summaryFile: $!\n";
|
|
|
90 |
my @line; # the line we'll build for output
|
|
|
91 |
# header line
|
|
|
92 |
print SUMMARY "user\tday\tip\t" . join( "\t", sort keys %headers ) . "\n";
|
|
|
93 |
# process each user
|
|
|
94 |
foreach my $user ( sort keys %activity ) {
|
|
|
95 |
push @line, $user;
|
|
|
96 |
my $timestamp = $activity{$user};
|
|
|
97 |
# process the date
|
|
|
98 |
foreach my $time ( sort keys %$timestamp ) {
|
|
|
99 |
push @line, $time;
|
|
|
100 |
my $ips = $$timestamp{$time};
|
|
|
101 |
# and the time
|
|
|
102 |
foreach my $ip ( sort keys %$ips ) {
|
|
|
103 |
push @line, $ip;
|
|
|
104 |
my $actions = $$ips{$ip};
|
|
|
105 |
# Finally, get the actions (all of them)
|
|
|
106 |
foreach my $action ( sort keys %headers ) {
|
|
|
107 |
push @line, $$actions{$action} ? $$actions{$action} : 0;
|
|
|
108 |
}
|
|
|
109 |
# finished with all the actions, so dump the line
|
|
|
110 |
print SUMMARY join( "\t", @line ) . "\n";
|
|
|
111 |
# and delete all the actions for a new IP
|
|
|
112 |
delete @line[2..$#line];
|
|
|
113 |
} # ip
|
|
|
114 |
# delete the IP also for a new timestamp
|
|
|
115 |
delete @line[1..$#line];
|
|
|
116 |
} # timestamp
|
|
|
117 |
# completely reset @line for a new user
|
|
|
118 |
@line = ();
|
|
|
119 |
} # user
|
|
|
120 |
close SUMMARY;
|
|
|
121 |
|
|
|
122 |
&mailLog();
|
|
|
123 |
|
|
|
124 |
1;
|