Merge remote-tracking branch 'origin/topic/robin/pp-alarms'

* origin/topic/robin/pp-alarms:
  The silliest, tiniest little whitespace fixes.
  Update missing in last commit to this branch.
  Adding test for alarm mail.
  Tuning the pretty-printed alarms output.
This commit is contained in:
Seth Hall 2012-01-04 13:41:28 -05:00
commit f8ec98625d
3 changed files with 92 additions and 53 deletions

View file

@ -10,18 +10,22 @@ module Notice;
export {
## Activate pretty-printed alarm summaries.
const pretty_print_alarms = T &redef;
## Address to send the pretty-printed reports to. Default if not set is
## :bro:id:`Notice::mail_dest`.
const mail_dest_pretty_printed = "" &redef;
## If an address from one of these networks is reported, we mark
## If an address from one of these networks is reported, we mark
## the entry with an addition quote symbol (i.e., ">"). Many MUAs
## then highlight such lines differently.
global flag_nets: set[subnet] &redef;
## Function that renders a single alarm. Can be overidden.
global pretty_print_alarm: function(out: file, n: Info) &redef;
## Force generating mail file, even if reading from traces or no mail
## destination is defined. This is mainly for testing.
global force_email_summaries = F &redef;
}
# We maintain an old-style file recording the pretty-printed alarms.
@ -32,6 +36,9 @@ global pp_alarms_open: bool = F;
# Returns True if pretty-printed alarm summaries are activated.
function want_pp() : bool
{
if ( force_email_summaries )
return T;
return (pretty_print_alarms && ! reading_traces()
&& (mail_dest != "" || mail_dest_pretty_printed != ""));
}
@ -41,38 +48,49 @@ function pp_open()
{
if ( pp_alarms_open )
return;
pp_alarms_open = T;
pp_alarms = open(pp_alarms_name);
local dest = mail_dest_pretty_printed != "" ? mail_dest_pretty_printed
: mail_dest;
local headers = email_headers("Alarm summary", dest);
write_file(pp_alarms, headers + "\n");
}
# Closes and mails out the current output file.
function pp_send()
function pp_send(rinfo: Log::RotationInfo)
{
if ( ! pp_alarms_open )
return;
write_file(pp_alarms, "\n\n--\n[Automatically generated]\n\n");
close(pp_alarms);
system(fmt("/bin/cat %s | %s -t -oi && /bin/rm %s",
pp_alarms_name, sendmail, pp_alarms_name));
pp_alarms_open = F;
local from = strftime("%H:%M:%S", rinfo$open);
local to = strftime("%H:%M:%S", rinfo$close);
local subject = fmt("Alarm summary from %s-%s", from, to);
local dest = mail_dest_pretty_printed != "" ? mail_dest_pretty_printed
: mail_dest;
if ( dest == "" )
# No mail destination configured, just leave the file alone. This is mainly for
# testing.
return;
local headers = email_headers(subject, dest);
local header_name = pp_alarms_name + ".tmp";
local header = open(header_name);
write_file(header, headers + "\n");
close(header);
system(fmt("/bin/cat %s %s | %s -t -oi && /bin/rm -f %s %s",
header_name, pp_alarms_name, sendmail, header_name, pp_alarms_name));
}
# Postprocessor function that triggers the email.
function pp_postprocessor(info: Log::RotationInfo): bool
{
if ( want_pp() )
pp_send();
pp_send(info);
return T;
}
@ -80,7 +98,7 @@ event bro_init()
{
if ( ! want_pp() )
return;
# This replaces the standard non-pretty-printing filter.
Log::add_filter(Notice::ALARM_LOG,
[$name="alarm-mail", $writer=Log::WRITER_NONE,
@ -92,13 +110,13 @@ event notice(n: Notice::Info) &priority=-5
{
if ( ! want_pp() )
return;
if ( ACTION_LOG !in n$actions )
if ( ACTION_ALARM !in n$actions )
return;
if ( ! pp_alarms_open )
pp_open();
pretty_print_alarm(pp_alarms, n);
}
@ -108,12 +126,12 @@ function do_msg(out: file, n: Info, line1: string, line2: string, line3: string,
@ifdef ( Notice::ACTION_ADD_GEODATA ) # Make tests happy, cyclic dependency.
if ( n?$remote_location && n$remote_location?$country_code )
country = fmt(" (remote location %s)", n$remote_location$country_code);
@endif
@endif
line1 = cat(line1, country);
local resolved = "";
if ( host1 != 0.0.0.0 )
resolved = fmt("%s # %s = %s", resolved, host1, name1);
@ -133,64 +151,64 @@ function do_msg(out: file, n: Info, line1: string, line2: string, line3: string,
function pretty_print_alarm(out: file, n: Info)
{
local pdescr = "";
@if ( Cluster::is_enabled() )
pdescr = "local";
if ( n?$src_peer )
pdescr = n$src_peer?$descr ? n$src_peer$descr : fmt("%s", n$src_peer$host);
pdescr = fmt("<%s> ", pdescr);
@endif
local msg = fmt( "%s%s", pdescr, n$msg);
local who = "";
local h1 = 0.0.0.0;
local h2 = 0.0.0.0;
local orig_p = "";
local resp_p = "";
if ( n?$id )
{
orig_p = fmt(":%s", n$id$orig_p);
resp_p = fmt(":%s", n$id$resp_p);
h1 = n$id$orig_h;
h2 = n$id$resp_h;
who = fmt("%s:%s -> %s:%s", h1, n$id$orig_p, h2, n$id$resp_p);
}
if ( n?$src && n?$dst )
else if ( n?$src && n?$dst )
{
h1 = n$src;
h2 = n$dst;
who = fmt("%s%s -> %s%s", h1, orig_p, h2, resp_p);
if ( n?$uid )
who = fmt("%s (uid %s)", who, n$uid );
who = fmt("%s -> %s", h1, h2);
}
else if ( n?$src )
{
local p = "";
if ( n?$p )
p = fmt(":%s", n$p);
h1 = n$src;
who = fmt("%s%s", h1, p);
who = fmt("%s%s", h1, (n?$p ? fmt(":%s", n$p) : ""));
}
if ( n?$uid )
who = fmt("%s (uid %s)", who, n$uid );
local flag = (h1 in flag_nets || h2 in flag_nets);
local line1 = fmt(">%s %D %s %s", (flag ? ">" : " "), network_time(), n$note, who);
local line2 = fmt(" %s", msg);
local line3 = n?$sub ? fmt(" %s", n$sub) : "";
if ( h1 == 0.0.0.0 )
{
do_msg(out, n, line1, line2, line3, h1, "", h2, "");
return;
}
if ( reading_traces() )
{
do_msg(out, n, line1, line2, line3, h1, "<skipped>", h2, "<skipped>");
return;
}
when ( local h1name = lookup_addr(h1) )
{
if ( h2 == 0.0.0.0 )