[1] | 1 | #! /usr/bin/perl
|
---|
| 2 |
|
---|
| 3 |
|
---|
| 4 | #
|
---|
| 5 |
|
---|
| 6 | # This tool will help extract the XML log file produced by Samhain
|
---|
| 7 | # Put it into a more readable format that can then be run by CRON
|
---|
| 8 | # and e-mailed to a user.
|
---|
| 9 | #
|
---|
| 10 | # Created: Ben <ben@deephouse.co.za>
|
---|
| 11 | #
|
---|
| 12 | #
|
---|
| 13 | # Updates:
|
---|
| 14 | # JUL 05 ver 1.1: - Updata to add in checkpint subroutine, this checks
|
---|
| 15 | # the scalar length
|
---|
| 16 | # that is return from the log file if is is a good size
|
---|
| 17 | # the program gets the value, if not value is returned it will not print it
|
---|
| 18 | # to the report.
|
---|
| 19 | #
|
---|
| 20 | # JUL 07 ver 1.2: - Update to the Code to handle reporting selection
|
---|
| 21 | # from the command line.
|
---|
| 22 | # Users are able to pass in [ReadOnly][LogFiles][Attributes].
|
---|
| 23 | # Better support for date
|
---|
| 24 | #
|
---|
| 25 | # Version: 1.2
|
---|
| 26 |
|
---|
| 27 |
|
---|
| 28 |
|
---|
| 29 |
|
---|
| 30 |
|
---|
| 31 | use strict;
|
---|
| 32 |
|
---|
| 33 | use XML::Simple;
|
---|
| 34 |
|
---|
| 35 | use Tie::File;
|
---|
| 36 |
|
---|
| 37 | use POSIX qw(strftime);
|
---|
| 38 |
|
---|
| 39 | my $date=strftime("%a %b %d %H:%M:%S %Y", localtime());
|
---|
| 40 |
|
---|
| 41 | my $tdate = `date +'%m%d%y'`; # Just to time stamp the files
|
---|
| 42 |
|
---|
| 43 | my $hostname = `hostname`; chomp($hostname);
|
---|
| 44 |
|
---|
| 45 | my $policy = $ARGV[1];
|
---|
| 46 |
|
---|
| 47 |
|
---|
| 48 |
|
---|
| 49 | &main();
|
---|
| 50 |
|
---|
| 51 |
|
---|
| 52 |
|
---|
| 53 | sub main {
|
---|
| 54 |
|
---|
| 55 |
|
---|
| 56 |
|
---|
| 57 | unless (@ARGV == 2) { printf("Usage: $0 Samhain_report.xml <policyname. ReadOnly> \n"); exit(0); }
|
---|
| 58 |
|
---|
| 59 | printf("## Reporting Starting\n");
|
---|
| 60 |
|
---|
| 61 | &eatfile();
|
---|
| 62 |
|
---|
| 63 | &extractdata($policy);
|
---|
| 64 |
|
---|
| 65 | printf("## Report completed\n");
|
---|
| 66 |
|
---|
| 67 | printf("## Your new report file has been created : Samhain-report-$hostname.$tdate\n");
|
---|
| 68 |
|
---|
| 69 | }
|
---|
| 70 |
|
---|
| 71 |
|
---|
| 72 |
|
---|
| 73 | # This routine will pull the data from the XML file, and sort through it
|
---|
| 74 |
|
---|
| 75 | # and look for the policy for [ReadOnly], once it has bfound that it will detected all the changes
|
---|
| 76 |
|
---|
| 77 | # within the policy
|
---|
| 78 |
|
---|
| 79 | #
|
---|
| 80 |
|
---|
| 81 | sub extractdata {
|
---|
| 82 |
|
---|
| 83 | my $xmlfile = $ARGV[0];
|
---|
| 84 |
|
---|
| 85 | my $config = XMLin($xmlfile);
|
---|
| 86 |
|
---|
| 87 | # Create new report file
|
---|
| 88 |
|
---|
| 89 | open(RP, ">fmre_report-$hostname.$tdate") || die ("Unable to open new report file, $!\n");
|
---|
| 90 |
|
---|
| 91 | printf RP ("Samhain CRITICAL REPORT FOR $hostname\n");
|
---|
| 92 |
|
---|
| 93 | printf RP ("\n");
|
---|
| 94 |
|
---|
| 95 | printf RP ("This report was created on : $date\n");
|
---|
| 96 |
|
---|
| 97 | printf RP ("Samhain Reporting Tool version 1.0\n");
|
---|
| 98 |
|
---|
| 99 | printf RP ("Created: Ben Cuthbert <benjamin.cuthbert\@db.com>\n");
|
---|
| 100 |
|
---|
| 101 | printf RP ("\n");
|
---|
| 102 |
|
---|
| 103 | printf RP ("Report for !! $_[0] Policy !!\n");
|
---|
| 104 |
|
---|
| 105 | printf RP ("\n");
|
---|
| 106 |
|
---|
| 107 | # STart getting all of the data from xml file
|
---|
| 108 |
|
---|
| 109 | foreach my $alert (@{$config->{'LOG'}}) {
|
---|
| 110 |
|
---|
| 111 | if($alert->{msg} =~ /POLICY \[$_[0]]/) { # Check we are on the correct policy
|
---|
| 112 |
|
---|
| 113 | print RP ("File Changed: $alert->{path}\n");
|
---|
| 114 |
|
---|
| 115 | &checkprint("$alert->{mtime_new}","Time Changed Old: $alert->{mtime_new}");
|
---|
| 116 |
|
---|
| 117 | &checkprint("$alert->{mtime_new}","Time Changed New: $alert->{mtime_old}");
|
---|
| 118 |
|
---|
| 119 | &checkprint("$alert->{mode_old}","Mode Old: $alert->{mode_old}");
|
---|
| 120 |
|
---|
| 121 | &checkprint("$alert->{mode_new}","Mode New: $alert->{mode_new}");
|
---|
| 122 |
|
---|
| 123 | &checkprint("$alert->{chksum_old}","CheckSum Old: $alert->{chksum_old}");
|
---|
| 124 |
|
---|
| 125 | &checkprint("$alert->{chksum_new}","CheckSum New: $alert->{chksum_new}");
|
---|
| 126 |
|
---|
| 127 | &checkprint("$alert->{size_new}","Size New: $alert->{size_new}");
|
---|
| 128 |
|
---|
| 129 | &checkprint("$alert->{size_old}","Size Old: $alert->{size_old}");
|
---|
| 130 |
|
---|
| 131 | printf RP ("\n");
|
---|
| 132 |
|
---|
| 133 | }
|
---|
| 134 |
|
---|
| 135 | }
|
---|
| 136 |
|
---|
| 137 | printf RP ("Created Using: Samhain XML Reporting tool.\n");
|
---|
| 138 |
|
---|
| 139 | printf RP ("Created By: Ben Cuthbert ben\@deephouse.co.za.\n");
|
---|
| 140 |
|
---|
| 141 | close(RP);
|
---|
| 142 |
|
---|
| 143 | }
|
---|
| 144 |
|
---|
| 145 |
|
---|
| 146 |
|
---|
| 147 | # This helps with logs that do not have Entires for Certain modes ie --rwx
|
---|
| 148 |
|
---|
| 149 | # Get the scalar back, check the lenght then print out if the lenght is
|
---|
| 150 |
|
---|
| 151 | # bigger than 1
|
---|
| 152 |
|
---|
| 153 | sub checkprint {
|
---|
| 154 |
|
---|
| 155 | chomp;
|
---|
| 156 |
|
---|
| 157 | my $l = length($_[0]);
|
---|
| 158 |
|
---|
| 159 | if($l gt 1) {
|
---|
| 160 |
|
---|
| 161 | printf RP ("$_[1]\n");
|
---|
| 162 |
|
---|
| 163 | }
|
---|
| 164 |
|
---|
| 165 | }
|
---|
| 166 |
|
---|
| 167 | # We need to change the structure of the HRML file from FMRE
|
---|
| 168 |
|
---|
| 169 | # so that we have the following tree structure.
|
---|
| 170 |
|
---|
| 171 | #VAR1 = {
|
---|
| 172 |
|
---|
| 173 | # 'LOG' => [
|
---|
| 174 |
|
---|
| 175 | # {
|
---|
| 176 |
|
---|
| 177 | # 'msg' = 'value'
|
---|
| 178 |
|
---|
| 179 | #
|
---|
| 180 |
|
---|
| 181 | # The reason for this is it makes extraction better.
|
---|
| 182 |
|
---|
| 183 | #
|
---|
| 184 |
|
---|
| 185 | # So we open XML file and enter the following details.
|
---|
| 186 |
|
---|
| 187 | # <config> please at top of file
|
---|
| 188 |
|
---|
| 189 | # </config> place at bottom of file
|
---|
| 190 |
|
---|
| 191 | # </trail><trail> remove trails, as we do not require them as
|
---|
| 192 |
|
---|
| 193 | # log files are rotated every day.
|
---|
| 194 |
|
---|
| 195 | # reports will only run on the day.
|
---|
| 196 |
|
---|
| 197 | sub eatfile {
|
---|
| 198 |
|
---|
| 199 | # Search and reaplce log with LOG, makes it easy
|
---|
| 200 |
|
---|
| 201 | open(FH, "$ARGV[0]") || die ("Unable to ammend file \n");
|
---|
| 202 |
|
---|
| 203 | open(FW, ">tmp.xml") || die ("Unable to ammend file \n");
|
---|
| 204 |
|
---|
| 205 | while (<FH>) {
|
---|
| 206 |
|
---|
| 207 | $_ =~ s/^---*//g; $_ =~ s/log/LOG/g; $_ =~ s/<trail>//g; $_ =~ s/<\/trail>//g; $_ =~ s/Log file printed//g;
|
---|
| 208 |
|
---|
| 209 | printf FW $_;
|
---|
| 210 |
|
---|
| 211 | }
|
---|
| 212 |
|
---|
| 213 | close(FW); close(FH); system("mv tmp.xml $ARGV[0]");
|
---|
| 214 |
|
---|
| 215 | # Put in <config> & </config> at top and bottom
|
---|
| 216 |
|
---|
| 217 | open(FH, ">>$ARGV[0]") || die ("Unable to ammend file \n");
|
---|
| 218 |
|
---|
| 219 | seek FH,0,2;
|
---|
| 220 |
|
---|
| 221 | printf FH "</config>";
|
---|
| 222 |
|
---|
| 223 | close(FH);
|
---|
| 224 |
|
---|
| 225 | ## Star the insert at the top and bottom, close the config </config>
|
---|
| 226 |
|
---|
| 227 | tie(my @FH1, 'Tie::File', $ARGV[0]) or die("Unable to read file, $!\n");
|
---|
| 228 |
|
---|
| 229 | unshift @FH1, '<config>';
|
---|
| 230 |
|
---|
| 231 | untie @FH1;
|
---|
| 232 |
|
---|
| 233 | printf ("Xml file has been modified to run with this program \n");
|
---|
| 234 |
|
---|
| 235 | }
|
---|
| 236 |
|
---|
| 237 |
|
---|
| 238 |
|
---|
| 239 |
|
---|