mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
Checkpoint for logging framework
This commit is contained in:
parent
aa0691ba21
commit
f3b148b019
5 changed files with 139 additions and 1 deletions
93
policy/logging.bro
Normal file
93
policy/logging.bro
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
module Logging;
|
||||||
|
|
||||||
|
export {
|
||||||
|
# The set of writers Bro provides.
|
||||||
|
type Writer: enum {
|
||||||
|
WRITER_DEFAULT, # See default_writer below.
|
||||||
|
WRITER_CSV,
|
||||||
|
WRITER_DATA_SERIES,
|
||||||
|
WRITER_SYSLOG
|
||||||
|
};
|
||||||
|
|
||||||
|
# Each stream gets a unique ID. This type will be extended by
|
||||||
|
# other scripts.
|
||||||
|
type ID: enum {
|
||||||
|
Unknown
|
||||||
|
};
|
||||||
|
|
||||||
|
# The default writer to use if a filter does not specify
|
||||||
|
# anything else.
|
||||||
|
const default_writer = WRITER_CSV &redef;
|
||||||
|
|
||||||
|
# Type defining a stream.
|
||||||
|
type Stream: record {
|
||||||
|
id : ID; # The ID of the stream.
|
||||||
|
columns : any; # A record type defining the stream's output columns.
|
||||||
|
};
|
||||||
|
|
||||||
|
# A filter defining what to record.
|
||||||
|
type Filter: record {
|
||||||
|
# A name to reference this filter.
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
# A predicate returning True if the filter wants a log entry
|
||||||
|
# to be recorded. If not given, an implicit True is assumed
|
||||||
|
# for all entries. The predicate receives one parameter:
|
||||||
|
# an instance of the log's record type with the fields to be
|
||||||
|
# logged.
|
||||||
|
pred: function(log: any) &optional;
|
||||||
|
|
||||||
|
# A path for outputting everything matching this
|
||||||
|
# filter. The path is either a string, or a function
|
||||||
|
# called with a single ``ID`` argument and returning a string.
|
||||||
|
#
|
||||||
|
# The specific interpretation of the string is left to the
|
||||||
|
# Writer, but if it's refering to a file, it's assumed that no
|
||||||
|
# extension is given; the writer will add whatever is
|
||||||
|
# appropiate.
|
||||||
|
path: any &optional;
|
||||||
|
|
||||||
|
# A subset of column names to record. If not given, all
|
||||||
|
# columns are recorded.
|
||||||
|
select: set[string] &optional;
|
||||||
|
|
||||||
|
# An event that is raised whenever the filter is applied
|
||||||
|
# to an entry. The event receives the same parameter
|
||||||
|
# as the predicate. It will always be generated,
|
||||||
|
# independent of what the predicate returns.
|
||||||
|
ev: event(c: connection, log: any) &optional;
|
||||||
|
|
||||||
|
# The writer to use.
|
||||||
|
writer: Writer &default=default_writer;
|
||||||
|
};
|
||||||
|
|
||||||
|
global filters: table[ID] of set[Filter];
|
||||||
|
|
||||||
|
# Logs the record "rec" to the stream "id". The type of
|
||||||
|
# "rec" must match the stream's "columns" field.
|
||||||
|
global log: function(id: ID, rec: any);
|
||||||
|
|
||||||
|
# Returns an existing filter previously installed for stream
|
||||||
|
# "id" under the given "name". If no such filter exists,
|
||||||
|
# the record "NoSuchFilter" is returned.
|
||||||
|
global get_filter: function(id: ID, name: string) : Filter;
|
||||||
|
|
||||||
|
global create: function(stream: Stream);
|
||||||
|
global add_filter: function(id: ID, filter: Filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
# Sentinel representing an unknown filter.
|
||||||
|
const NoSuchFilter: Filter = [$name="<unknown filter>"];
|
||||||
|
|
||||||
|
function add_filter(id: ID, filter: Filter)
|
||||||
|
{
|
||||||
|
if ( id !in filters )
|
||||||
|
filters[id] = set();
|
||||||
|
|
||||||
|
add filters[id][filter];
|
||||||
|
}
|
||||||
|
|
||||||
|
function log(id: ID, rec: any)
|
||||||
|
{
|
||||||
|
logging_log(id, rec);
|
||||||
|
}
|
27
policy/test-logging.bro
Normal file
27
policy/test-logging.bro
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
module SSH;
|
||||||
|
|
||||||
|
@load logging
|
||||||
|
|
||||||
|
# Create a new ID for our log stream
|
||||||
|
redef enum Logging::ID += { SSH };
|
||||||
|
|
||||||
|
# Define a record with all the columns the log file can have.
|
||||||
|
# (I'm using a subset of fields from ssh-ext for demonstration.)
|
||||||
|
type Log: record {
|
||||||
|
t: time;
|
||||||
|
id: conn_id; # Will be rolled out into individual columns.
|
||||||
|
status: string &optional;
|
||||||
|
country: string &default="unknown";
|
||||||
|
};
|
||||||
|
|
||||||
|
event bro_init()
|
||||||
|
{
|
||||||
|
# Create the stream.
|
||||||
|
Logging::create([$id=SSH, $columns=Log]);
|
||||||
|
|
||||||
|
# Add a default filter that simply logs everything to "ssh.log" using the default writer.
|
||||||
|
#Logging::add_filter(SSH, [$name="default", $path="ssh"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
# Log something.
|
||||||
|
Logging::log(SSH, [$t=network_time(), $status="ok"]);
|
|
@ -1336,7 +1336,9 @@ static int is_init_compat(const BroType* t1, const BroType* t2)
|
||||||
|
|
||||||
int same_type(const BroType* t1, const BroType* t2, int is_init)
|
int same_type(const BroType* t1, const BroType* t2, int is_init)
|
||||||
{
|
{
|
||||||
if ( t1 == t2 )
|
if ( t1 == t2 ||
|
||||||
|
t1->Tag() == TYPE_ANY ||
|
||||||
|
t2->Tag() == TYPE_ANY )
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
t1 = flatten_type(t1);
|
t1 = flatten_type(t1);
|
||||||
|
|
|
@ -3300,6 +3300,10 @@ Val* check_and_promote(Val* v, const BroType* t, int is_init)
|
||||||
|
|
||||||
TypeTag t_tag = t->Tag();
|
TypeTag t_tag = t->Tag();
|
||||||
TypeTag v_tag = vt->Tag();
|
TypeTag v_tag = vt->Tag();
|
||||||
|
|
||||||
|
// More thought definitely needs to go into this.
|
||||||
|
if ( t_tag == TYPE_ANY || v_tag == TYPE_ANY )
|
||||||
|
return v;
|
||||||
|
|
||||||
if ( ! EitherArithmetic(t_tag, v_tag) ||
|
if ( ! EitherArithmetic(t_tag, v_tag) ||
|
||||||
/* allow sets as initializers */
|
/* allow sets as initializers */
|
||||||
|
|
12
src/bro.bif
12
src/bro.bif
|
@ -359,6 +359,18 @@ function cat%(...%): string
|
||||||
|
|
||||||
return new StringVal(s);
|
return new StringVal(s);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
function logging_log%(id: Logging_ID, rec: any%): bool
|
||||||
|
%{
|
||||||
|
// Generate the log line event
|
||||||
|
// Lookup the log file
|
||||||
|
TableVal *f = opt_internal_table("Logging::filters");
|
||||||
|
TableVal *s = f->Lookup(id, 0)->AsTableVal();
|
||||||
|
|
||||||
|
// For each filter on 'id'
|
||||||
|
// Format the output
|
||||||
|
// Print the line
|
||||||
|
%}
|
||||||
|
|
||||||
function cat_sep%(sep: string, def: string, ...%): string
|
function cat_sep%(sep: string, def: string, ...%): string
|
||||||
%{
|
%{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue