Merge branch 'zeek:master' into master

This commit is contained in:
Fatema BW 2022-08-11 18:20:31 -07:00 committed by GitHub
commit d9632631ce
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
243 changed files with 44421 additions and 20773 deletions

View file

@ -538,6 +538,7 @@ hook Notice::notice(n: Notice::Info) &priority=-5
n$suppress_for != 0secs )
{
event Notice::begin_suppression(n$ts, n$suppress_for, n$note, n$identifier);
suppressing[n$note, n$identifier] = n$ts + n$suppress_for;
@if ( Cluster::is_enabled() && Cluster::local_node_type() != Cluster::MANAGER )
event Notice::manager_begin_suppression(n$ts, n$suppress_for, n$note, n$identifier);
@endif

View file

@ -0,0 +1 @@
@load ./main

View file

@ -0,0 +1,609 @@
##! Module for recording and querying metrics. This modules wraps
##! the lower-level telemetry.bif functions.
##!
##! Metrics will be exposed through a Prometheus HTTP endpoint when
##! enabled by setting :zeek:see:`Broker::metrics_port` or using the
##! `BROKER_METRICS_PORT` environment variable.
@load base/misc/version
module Telemetry;
export {
## Alias for a vector of label values.
type labels_vector: vector of string;
## Type that captures options used to create metrics.
type MetricOpts: record {
## The prefix (namespace) of the metric.
prefix: string;
## The human-readable name of the metric.
name: string;
## The unit of the metric. Use the pseudo-unit "1" if this is a unit-less metric.
unit: string;
## Documentation for this metric.
help_text: string;
## The label names (also called dimensions) of the metric. When
## instantiating or working with concrete metrics, corresponding
## label values have to be provided.
labels: vector of string &default=vector();
## Whether the metric represents something that is accumulating.
## Defaults to ``T`` for counters and ``F`` for gauges and
## histograms.
is_total: bool &optional;
## When creating a :zeek:see:`Telemetry::HistogramFamily`,
## describes the number and bounds of the individual buckets.
bounds: vector of double &optional;
## The same meaning as *bounds*, but as :zeek:type:`count`.
## Only set in the return value of
## :zeek:see:`Telemetry::collect_histogram_metrics`.
## for histograms when the underlying type is ``int64_t``,
## otherwise ignored.
count_bounds: vector of count &optional;
## Describes the underlying metric type.
## Only set in the return value of
## :zeek:see:`Telemetry::collect_metrics` or
## :zeek:see:`Telemetry::collect_histogram_metrics`,
## otherwise ignored.
metric_type: MetricType &optional;
};
## Type representing a family of counters with uninitialized label values.
##
## To create concrete :zeek:see:`Telemetry::Counter` instances, use
## :zeek:see:`Telemetry::counter_with`. To modify counters directly
## use :zeek:see:`Telemetry::counter_family_inc`.
type CounterFamily: record {
__family: opaque of dbl_counter_metric_family;
__labels: vector of string;
};
## Type representing a counter metric with initialized label values.
##
## Counter metrics only ever go up and reset when the process
## restarts. Use :zeek:see:`Telemetry::counter_inc` or
## :zeek:see:`Telemetry::counter_set` to modify counters.
## An example for a counter is the number of log writes
## per :zeek:see:`Log::Stream` or number connections broken down
## by protocol and service.
type Counter: record {
__metric: opaque of dbl_counter_metric;
};
## Register a counter family.
global register_counter_family: function(opts: MetricOpts): CounterFamily;
## Get a :zeek:see:`Telemetry::Counter` instance given family and label values.
global counter_with: function(cf: CounterFamily,
label_values: labels_vector &default=vector()): Counter;
## Increment a :zeek:see:`Telemetry::Counter` by `amount`.
## Using a negative `amount` is an error.
##
## c: The counter instance.
##
## amount: The amount by which to increment the counter.
##
## Returns: True if the counter was incremented successfully.
global counter_inc: function(c: Counter, amount: double &default=1.0): bool;
## Helper to set a :zeek:see:`Telemetry::Counter` to the given `value`.
## This can be useful for mirroring counter metrics in an
## :zeek:see:`Telemetry::sync` hook implementation.
## Setting a value that is less than the current value of the
## metric is an error and will be ignored.
##
## c: The counter instance.
##
## value: The value to set the counter to.
##
## Returns: True if the counter value was set successfully.
global counter_set: function(c: Counter, value: double): bool;
## Increment a :zeek:see:`Telemetry::Counter` through the :zeek:see:`Telemetry::CounterFamily`.
## This is a short-cut for :zeek:see:`Telemetry::counter_inc`.
## Using a negative amount is an error.
##
## cf: The counter family to use.
##
## label_values: The label values to use for the counter.
##
## amount: The amount by which to increment the counter.
##
## Returns: True if the counter was incremented successfully.
global counter_family_inc: function(cf: CounterFamily,
label_values: labels_vector &default=vector(),
amount: double &default=1.0): bool;
## Set a :zeek:see:`Telemetry::Counter` through the :zeek:see:`Telemetry::CounterFamily`.
## This is a short-cut for :zeek:see:`Telemetry::counter_set`.
## Setting a value that is less than the current value of the
## metric is an error and will be ignored.
##
## cf: The counter family to use.
##
## label_values: The label values to use for the counter.
##
## value: The value to set the counter to.
##
## Returns: True if the counter value was set successfully.
global counter_family_set: function(cf: CounterFamily,
label_values: labels_vector,
value: double): bool;
## Type representing a family of gauges with uninitialized label values.
##
## Create concrete :zeek:see:`Telemetry::Gauge` instances with
## :zeek:see:`Telemetry::gauge_with`, or use
## :zeek:see:`Telemetry::gauge_family_inc` or
## :zeek:see:`Telemetry::gauge_family_set` directly.
type GaugeFamily: record {
__family: opaque of dbl_gauge_metric_family;
__labels: vector of string;
};
## Type representing a gauge metric with initialized label values.
##
## Use :zeek:see:`Telemetry::gauge_inc`, :zeek:see:`Telemetry::gauge_dec`,
## or :zeek:see:`Telemetry::gauge_set` to modify the gauge.
## Example for gauges are process memory usage, table sizes
## or footprints of long-lived values as determined by
## :zeek:see:`val_footprint`.
type Gauge: record {
__metric: opaque of dbl_gauge_metric;
};
## Register a gauge family.
global register_gauge_family: function(opts: MetricOpts): GaugeFamily;
## Get a :zeek:see:`Telemetry::Gauge` instance given family and label values.
global gauge_with: function(gf: GaugeFamily,
label_values: labels_vector &default=vector()): Gauge;
## Increment a :zeek:see:`Telemetry::Gauge` by `amount`.
##
## g: The gauge instance.
##
## amount: The amount by which to increment the gauge.
##
## Returns: True if the gauge was incremented successfully.
global gauge_inc: function(g: Gauge, amount: double &default=1.0): bool;
## Decrement a :zeek:see:`Telemetry::Gauge` by `amount`.
##
## g: The gauge instance.
##
## amount: The amount by which to decrement the gauge.
##
## Returns: True if the gauge was incremented successfully.
global gauge_dec: function(g: Gauge, amount: double &default=1.0): bool;
## Helper to set a :zeek:see:`Telemetry::Gauge` to the given `value`.
##
## g: The gauge instance.
##
## value: The value to set the gauge to.
##
## Returns: True if the gauge value was set successfully.
global gauge_set: function(g: Gauge, value: double): bool;
## Increment a :zeek:see:`Telemetry::Gauge` by the given `amount` through
## the :zeek:see:`Telemetry::GaugeFamily`.
## This is a short-cut for :zeek:see:`Telemetry::gauge_inc`.
## Using a negative amount is an error.
##
## gf: The gauge family to use.
##
## label_values: The label values to use for the gauge.
##
## amount: The amount by which to increment the gauge.
##
## Returns: True if the gauge was incremented successfully.
global gauge_family_inc: function(gf: GaugeFamily,
label_values: labels_vector &default=vector(),
amount: double &default=1.0): bool;
## Decrement a :zeek:see:`Telemetry::Gauge` by the given `amount` through
## the :zeek:see:`Telemetry::GaugeFamily`.
## This is a short-cut for :zeek:see:`Telemetry::gauge_dec`.
##
## gf: The gauge family to use.
##
## label_values: The label values to use for the gauge.
##
## amount: The amount by which to increment the gauge.
##
## Returns: True if the gauge was incremented successfully.
global gauge_family_dec: function(gf: GaugeFamily,
label_values: labels_vector &default=vector(),
amount: double &default=1.0): bool;
## Set a :zeek:see:`Telemetry::Gauge` to the given `value` through
## the :zeek:see:`Telemetry::GaugeFamily`.
## This is a short-cut for :zeek:see:`Telemetry::gauge_set`.
##
## gf: The gauge family to use.
##
## label_values: The label values to use for the gauge.
##
## value: The value to set the gauge to.
##
## Returns: True if the gauge value was set successfully.
global gauge_family_set: function(g: GaugeFamily,
label_values: labels_vector,
value: double): bool;
## Type representing a family of histograms with uninitialized label values.
## Create concrete :zeek:see:`Telemetry::Histogram` instances with
## :zeek:see:`Telemetry::histogram_with` or use
## :zeek:see:`Telemetry::histogram_family_observe` directly.
type HistogramFamily: record {
__family: opaque of dbl_histogram_metric_family;
__labels: vector of string;
};
## Type representing a histogram metric with initialized label values.
## Use :zeek:see:`Telemetry::histogram_observe` to make observations.
type Histogram: record {
__metric: opaque of dbl_histogram_metric;
};
## Register a histogram family.
global register_histogram_family: function(opts: MetricOpts): HistogramFamily;
## Get a :zeek:see:`Telemetry::Histogram` instance given family and label values.
global histogram_with: function(hf: HistogramFamily,
label_values: labels_vector &default=vector()): Histogram;
## Observe a measurement for a :zeek:see:`Telemetry::Histogram`.
##
## h: The histogram instance.
##
## measurement: The value for this observations.
##
## Returns: True if measurement was observed successfully.
global histogram_observe: function(h: Histogram, measurement: double): bool;
## Observe a measurement for a :zeek:see:`Telemetry::Histogram` through
## the :zeek:see:`Telemetry::HistogramFamily`.
## This is a short-cut for :zeek:see:`Telemetry::histogram_observe`.
##
## hf: The histogram family to use.
##
## label_values: The label values to use for the histogram.
##
## measurement: The value for this observations.
##
## Returns: True if measurement was observed successfully.
global histogram_family_observe: function(hf: HistogramFamily,
label_values: labels_vector,
measurement: double): bool;
## Telemetry sync hook.
##
## This hook is invoked every :zeek:see:`Telemetry::sync_interval`
## for script writers to synchronize or mirror metrics with the
## telemetry subsystem. For example, when tracking table or value
## footprints with gauges, the value in question can be set on an actual
## :zeek:see:`Telemetry::Gauge` instance during execution of this hook.
##
## Implementations should be lightweight, this hook may be called
## multiple times per minute. The interval can increased by changing
## :zeek:see:`Telemetry::sync_interval` at the cost of delaying
## metric updates and thereby reducing granularity.
global sync: hook();
## Interval at which the :zeek:see:`Telemetry::sync` hook is invoked.
option sync_interval = 10sec;
## Type of elements returned by the :zeek:see:`Telemetry::collect_metrics` function.
type Metric: record {
## A :zeek:see:`Telemetry::MetricOpts` record describing this metric.
opts: MetricOpts;
## The label values associated with this metric, if any.
labels: vector of string;
## The value of gauge or counter cast to a double
## independent of the underlying data type.
## This value is set for all counter and gauge metrics,
## it is unset for histograms.
value: double &optional;
## The value of the underlying gauge or counter as a double
## if the underlying metric type uses ``int64_t``.
## Only counters and gauges created with the C++ API may
## have this value set.
count_value: count &optional;
};
## Type of elements returned by the :zeek:see:`Telemetry::collect_histogram_metrics` function.
type HistogramMetric: record {
## A :zeek:see:`Telemetry::MetricOpts` record describing this histogram.
opts: MetricOpts;
## The label values associated with this histogram, if any.
labels: vector of string;
## Individual counters for each of the buckets as
## described by the *bounds* field in *opts*;
values: vector of double;
## If the underlying data type of the histogram is ``int64_t``,
## this vector will hold the values as counts, otherwise it
## is unset. Only histograms created with the C++ API have
## may have this value set.
count_values: vector of count &optional;
## The number of observations made for this histogram.
observations: double;
## The sum of all observations for this histogram.
sum: double;
## If the underlying data type of the histogram is ``int64_t``,
## the number of observations as :zeek:type:`count`, otherwise
## unset.
count_observations: count &optional;
## If the underlying data type of the histogram is ``int64_t``,
## the sum of all observations as :zeek:type:`count`, otherwise
## unset.
count_sum: count &optional;
};
## Collect all counter and gauge metrics matching the given *name* and *prefix*.
##
## For histogram metrics, use the :zeek:see:`Telemetry::collect_histogram_metrics`.
##
## The *prefix* and *name* parameters support globbing. By default,
## all counters and gauges are returned.
global collect_metrics: function(prefix: string &default="*",
name: string &default="*"): vector of Metric;
## Collect all histograms and their observations matching the given
## *prefix* and *name*.
##
## The *prefix* and *name* parameters support globbing. By default,
## all histogram metrics are returned.
global collect_histogram_metrics: function(prefix: string &default="*",
name: string &default="*"): vector of HistogramMetric;
}
## Internal helper to create the labels table.
function make_labels(keys: vector of string, values: labels_vector): table[string] of string
{
local labels: table[string] of string;
for ( i in keys )
labels[keys[i]] = values[i];
return labels;
}
function register_counter_family(opts: MetricOpts): CounterFamily
{
local f = Telemetry::__dbl_counter_family(
opts$prefix,
opts$name,
opts$labels,
opts$help_text,
opts$unit,
opts?$is_total ? opts$is_total : T
);
return CounterFamily($__family=f, $__labels=opts$labels);
}
# Fallback Counter returned when there are issues with the labels.
global error_counter_cf = register_counter_family([
$prefix="zeek",
$name="telemetry_counter_usage_error",
$unit="1",
$help_text="This counter is returned when label usage for counters is wrong. Check reporter.log if non-zero."
]);
function counter_with(cf: CounterFamily, label_values: labels_vector): Counter
{
if ( |cf$__labels| != |label_values| )
{
Reporter::error(fmt("Invalid label values expected %s, have %s", |cf$__labels|, |label_values|));
return counter_with(error_counter_cf);
}
local labels = make_labels(cf$__labels, label_values);
local m = Telemetry::__dbl_counter_metric_get_or_add(cf$__family, labels);
return Counter($__metric=m);
}
function counter_inc(c: Counter, amount: double): bool
{
return Telemetry::__dbl_counter_inc(c$__metric, amount);
}
function counter_set(c: Counter, value: double): bool
{
local cur_value: double = Telemetry::__dbl_counter_value(c$__metric);
if (value < cur_value)
{
Reporter::error(fmt("Attempted to set lower counter value=%s cur_value=%s", value, cur_value));
return F;
}
return Telemetry::__dbl_counter_inc(c$__metric, value - cur_value);
}
function counter_family_inc(cf: CounterFamily, label_values: labels_vector, amount: double): bool
{
return counter_inc(counter_with(cf, label_values), amount);
}
function counter_family_set(cf: CounterFamily, label_values: labels_vector, value: double): bool
{
return counter_set(counter_with(cf, label_values), value);
}
function register_gauge_family(opts: MetricOpts): GaugeFamily
{
local f = Telemetry::__dbl_gauge_family(
opts$prefix,
opts$name,
opts$labels,
opts$help_text,
opts$unit,
opts?$is_total ? opts$is_total : F
);
return GaugeFamily($__family=f, $__labels=opts$labels);
}
# Fallback Gauge returned when there are issues with the label usage.
global error_gauge_cf = register_gauge_family([
$prefix="zeek",
$name="telemetry_gauge_usage_error",
$unit="1",
$help_text="This gauge is returned when label usage for gauges is wrong. Check reporter.log if non-zero."
]);
function gauge_with(gf: GaugeFamily, label_values: labels_vector): Gauge
{
if ( |gf$__labels| != |label_values| )
{
Reporter::error(fmt("Invalid label values expected %s, have %s", |gf$__labels|, |label_values|));
return gauge_with(error_gauge_cf);
}
local labels = make_labels(gf$__labels, label_values);
local m = Telemetry::__dbl_gauge_metric_get_or_add(gf$__family, labels);
return Gauge($__metric=m);
}
function gauge_inc(g: Gauge, amount: double &default=1.0): bool
{
return Telemetry::__dbl_gauge_inc(g$__metric, amount);
}
function gauge_dec(g: Gauge, amount: double &default=1.0): bool
{
return Telemetry::__dbl_gauge_dec(g$__metric, amount);
}
function gauge_set(g: Gauge, value: double): bool
{
# Telemetry currently does not implement __dbl_gauge_set(), do
# it by hand here.
local cur_value: double = Telemetry::__dbl_gauge_value(g$__metric);
if (value > cur_value)
return Telemetry::__dbl_gauge_inc(g$__metric, value - cur_value);
return Telemetry::__dbl_gauge_dec(g$__metric, cur_value - value);
}
function gauge_family_inc(gf: GaugeFamily, label_values: labels_vector, value: double): bool
{
return gauge_inc(gauge_with(gf, label_values), value);
}
function gauge_family_dec(gf: GaugeFamily, label_values: labels_vector, value: double): bool
{
return gauge_dec(gauge_with(gf, label_values), value);
}
function gauge_family_set(gf: GaugeFamily, label_values: labels_vector, value: double): bool
{
return gauge_set(gauge_with(gf, label_values), value);
}
function register_histogram_family(opts: MetricOpts): HistogramFamily
{
local f = Telemetry::__dbl_histogram_family(
opts$prefix,
opts$name,
opts$labels,
opts$bounds,
opts$help_text,
opts$unit,
opts?$is_total ? opts$is_total : F
);
return HistogramFamily($__family=f, $__labels=opts$labels);
}
# Fallback Histogram when there are issues with the labels.
global error_histogram_hf = register_histogram_family([
$prefix="zeek",
$name="telemetry_histogram_usage_error",
$unit="1",
$help_text="This histogram is returned when label usage for histograms is wrong. Check reporter.log if non-zero.",
$bounds=vector(1.0)
]);
function histogram_with(hf: HistogramFamily, label_values: labels_vector): Histogram
{
if ( |hf$__labels| != |label_values| )
{
Reporter::error(fmt("Invalid label values expected %s, have %s", |hf$__labels|, |label_values|));
return histogram_with(error_histogram_hf);
}
local labels = make_labels(hf$__labels, label_values);
local m = Telemetry::__dbl_histogram_metric_get_or_add(hf$__family, labels);
return Histogram($__metric=m);
}
function histogram_observe(h: Histogram, measurement: double): bool
{
return Telemetry::__dbl_histogram_observe(h$__metric, measurement);
}
function histogram_family_observe(hf: HistogramFamily, label_values: labels_vector, measurement: double): bool
{
return histogram_observe(histogram_with(hf, label_values), measurement);
}
function collect_metrics(prefix: string, name: string): vector of Metric
{
return Telemetry::__collect_metrics(prefix, name);
}
function collect_histogram_metrics(prefix: string, name: string): vector of HistogramMetric
{
return Telemetry::__collect_histogram_metrics(prefix, name);
}
event run_sync_hook()
{
hook Telemetry::sync();
schedule sync_interval { run_sync_hook() };
}
event zeek_init()
{
schedule sync_interval { run_sync_hook() };
}
# Expose the Zeek version as Prometheus style info metric
global version_gauge_family = Telemetry::register_gauge_family([
$prefix="zeek",
$name="version_info",
$unit="1",
$help_text="The Zeek version",
$labels=vector("version_number", "major", "minor", "patch", "commit",
"beta", "debug","version_string")
]);
event zeek_init()
{
local v = Version::info;
local labels = vector(cat(v$version_number),
cat(v$major), cat(v$minor), cat (v$patch),
cat(v$commit),
v$beta ? "true" : "false",
v$debug ? "true" : "false",
v$version_string);
Telemetry::gauge_family_set(version_gauge_family, labels, 1.0);
}

View file

@ -588,6 +588,23 @@ type fa_metadata: record {
inferred: bool &default=T;
};
## A hook taking a connection, analyzer tag and analyzer id that can be
## used to veto disabling analyzers. Specifically, an analyzer can be prevented
## from being disabled by using a :zeek:see:`break` statement within the hook.
## This hook is invoked synchronously during a :zeek:see:`disable_analyzer` call.
##
## Scripts implementing this hook should have other logic that will eventually
## disable the analyzer for the given connection. That is, if a script vetoes
## disabling an analyzer, it takes responsibility for a later call to
## :zeek:see:`disable_analyzer`, which may be never.
##
## c: The connection
##
## atype: The type / tag of the analyzer being disabled.
##
## aid: The analyzer ID.
type disabling_analyzer: hook(c: connection, atype: AllAnalyzers::Tag, aid: count);
## Fields of a SYN packet.
##
## .. zeek:see:: connection_SYN_packet

View file

@ -43,6 +43,7 @@
@load base/frameworks/tunnels
@load base/frameworks/openflow
@load base/frameworks/netcontrol
@load base/frameworks/telemetry
@load base/protocols/conn
@load base/protocols/dce-rpc

View file

@ -91,6 +91,12 @@ export {
## transaction narrative.
option DHCP::max_txid_watch_time = 30secs;
## The maximum number of uids allowed in a single log entry.
option DHCP::max_uids_per_log_entry = 10;
## The maximum number of msg_types allowed in a single log entry.
option DHCP::max_msg_types_per_log_entry = 50;
## This event is used internally to distribute data around clusters
## since DHCP doesn't follow the normal "connection" model used by
## most protocols. It can also be handled to extend the DHCP log.
@ -266,6 +272,13 @@ event DHCP::aggregate_msgs(ts: time, id: conn_id, uid: string, is_orig: bool, ms
if ( options?$lease )
log_info$lease_time = options$lease;
}
# Write log entry if |uids| or |msg_types| becomes too large
if ( |log_info$uids| >= max_uids_per_log_entry || |log_info$msg_types| >= max_msg_types_per_log_entry )
{
Log::write(LOG, log_info);
delete join_data[msg$xid];
}
}
@endif

View file

@ -16,8 +16,14 @@ export {
uid: string &log;
## Identifier for the connection.
id: conn_id &log;
## Modbus transaction ID
tid: count &log &optional;
## The terminal unit identifier for the message
unit: count &log &optional;
## The name of the function message that was sent.
func: string &log &optional;
## Whether this PDU was a response ("RESP") or request ("REQ")
pdu_type: string &log &optional;
## The exception if the response was a failure.
exception: string &log &optional;
};
@ -48,14 +54,18 @@ event modbus_message(c: connection, headers: ModbusHeaders, is_orig: bool) &prio
}
c$modbus$ts = network_time();
c$modbus$tid = headers$tid;
c$modbus$unit = headers$uid;
c$modbus$func = function_codes[headers$function_code];
## If this message is from the TCP originator, it is a request. Otherwise,
## it is a response.
c$modbus$pdu_type = is_orig ? "REQ" : "RESP";
}
event modbus_message(c: connection, headers: ModbusHeaders, is_orig: bool) &priority=-5
{
# Only log upon replies.
# Also, don't log now if this is an exception (log in the exception event handler)
if ( ! is_orig && ( headers$function_code <= 0x81 || headers$function_code >= 0x98 ) )
# Don't log now if this is an exception (log in the exception event handler)
if ( headers$function_code <= 0x81 || headers$function_code >= 0x98 )
Log::write(LOG, c$modbus);
}

View file

@ -255,10 +255,8 @@ function finish(c: connection, remove_analyzer: bool)
{
log_record(c$ssl);
if ( remove_analyzer && disable_analyzer_after_detection && c?$ssl && c$ssl?$analyzer_id )
{
disable_analyzer(c$id, c$ssl$analyzer_id);
delete c$ssl$analyzer_id;
}
if ( disable_analyzer(c$id, c$ssl$analyzer_id) )
delete c$ssl$analyzer_id;
}
event ssl_client_hello(c: connection, version: count, record_version: count, possible_ts: time, client_random: string, session_id: string, ciphers: index_vec, comp_methods: index_vec) &priority=5

View file

@ -58,7 +58,7 @@ function extract_first_email_addr(str: string): string
function split_mime_email_addresses(line: string): set[string]
{
local output = string_set();
local addrs = find_all(line, /(\"[^"]*\")?[^,]+/);
local addrs = find_all(line, /(\"[^"]*\")?[^,]+@[^,]+/);
for ( part in addrs )
{
add output[strip(part)];

View file

@ -234,13 +234,38 @@ function get_emails(a: addr): string
return fmt_email_string(find_all_emails(a));
}
event zeek_init() &priority=10
function update_local_nets_table(id: string, new_value: set[subnet]): set[subnet]
{
# Create the local_nets mapping table.
for ( cidr in new_value )
local_nets_table[cidr] = cidr;
return new_value;
}
function update_local_zones_regex(id: string, new_value: set[string]): set[string]
{
# Double backslashes are needed due to string parsing.
local_dns_suffix_regex = set_to_regex(local_zones, "(^\\.?|\\.)(~~)$");
local_dns_neighbor_suffix_regex = set_to_regex(neighbor_zones, "(^\\.?|\\.)(~~)$");
# Create the local_nets mapping table.
for ( cidr in Site::local_nets )
local_nets_table[cidr] = cidr;
local_dns_suffix_regex = set_to_regex(new_value, "(^\\.?|\\.)(~~)$");
return new_value;
}
function update_neighbor_zones_regex(id: string, new_value: set[string]): set[string]
{
local_dns_neighbor_suffix_regex = set_to_regex(new_value, "(^\\.?|\\.)(~~)$");
return new_value;
}
event zeek_init() &priority=10
{
# Have these run with a lower priority so we account for additions/removals
# from user created change handlers.
Option::set_change_handler("Site::local_nets", update_local_nets_table, -5);
Option::set_change_handler("Site::local_zones", update_local_zones_regex, -5);
Option::set_change_handler("Site::neighbor_zones", update_neighbor_zones_regex, -5);
# Use change handler to initialize local_nets mapping table and zones
# regexes.
update_local_nets_table("Site::local_nets", Site::local_nets);
update_local_zones_regex("Site::local_zones", Site::local_zones);
update_neighbor_zones_regex("Site::neighbor_zones", Site::neighbor_zones);
}

View file

@ -204,7 +204,7 @@ function send_deploy_response(req: Management::Request::Request)
}
Management::Log::info(fmt("tx Management::Agent::API::deploy_response %s",
Management::result_to_string(res)));
Management::result_vec_to_string(req$results)));
Broker::publish(agent_topic(),
Management::Agent::API::deploy_response, req$id, req$results);
@ -262,6 +262,8 @@ event Management::Agent::Runtime::trigger_log_archival(run_archival: bool)
event Management::Supervisor::API::notify_node_exit(node: string, outputs: Management::NodeOutputs)
{
Management::Log::info(fmt("rx Management::Supervisor::API::notify_node_exit %s", node));
if ( node in g_nodes )
g_outputs[node] = outputs;
}
@ -753,7 +755,8 @@ event Management::Node::API::node_dispatch_response(reqid: string, result: Manag
event Management::Agent::API::node_dispatch_request(reqid: string, action: vector of string, nodes: set[string])
{
Management::Log::info(fmt("rx Management::Agent::API::node_dispatch_request %s %s %s", reqid, action, nodes));
Management::Log::info(fmt("rx Management::Agent::API::node_dispatch_request %s %s %s",
reqid, action, Management::Util::set_to_vector(nodes)));
local node: string;
local cluster_nodes: set[string];

View file

@ -1174,11 +1174,11 @@ event Management::Controller::API::get_id_value_request(reqid: string, id: strin
local res: Management::Result;
# Special case: if we have no instances, respond right away.
if ( |g_instances_known| == 0 )
# Special case: if we have no deployed cluster, respond right away.
if ( |g_instances| == 0 )
{
Management::Log::info(fmt("tx Management::Controller::API::get_id_value_response %s", reqid));
res = Management::Result($reqid=reqid, $success=F, $error="no instances connected");
res = Management::Result($reqid=reqid, $success=F, $error="no cluster deployed");
Broker::publish(Management::Controller::topic,
Management::Controller::API::get_id_value_response,
reqid, vector(res));

View file

@ -57,7 +57,8 @@ global g_dispatch_table: table[string] of DispatchCallback = {
event Management::Node::API::node_dispatch_request(reqid: string, action: vector of string, nodes: set[string])
{
Management::Log::info(fmt("rx Management::Node::API::node_dispatch_request %s %s %s", reqid, action, nodes));
Management::Log::info(fmt("rx Management::Node::API::node_dispatch_request %s %s %s",
reqid, action, Management::Util::set_to_vector(nodes)));
if ( |nodes| > 0 && Cluster::node !in nodes )
{
@ -102,7 +103,10 @@ event Broker::peer_added(peer: Broker::EndpointInfo, msg: string)
# If this is the agent peering, notify it that we're ready
if ( peer$network$address == epi$network$address &&
peer$network$bound_port == epi$network$bound_port )
{
Management::Log::info(fmt("tx Management::Node::API::notify_node_hello %s", Cluster::node));
Broker::publish(node_topic, Management::Node::API::notify_node_hello, Cluster::node);
}
}
event zeek_init()

View file

@ -0,0 +1,199 @@
##! Implementation of a telemetry.log and telemetry_histogram.log file
##! using metrics accessible via the Telemetry module.
@load base/frameworks/telemetry
module Telemetry;
export {
redef enum Log::ID += { LOG, LOG_HISTOGRAM };
## How often metrics are reported.
option log_interval = 60sec;
## Only metrics with prefixes in this set will be included in the
## `telemetry.log` and `telemetry_histogram.log` files by default.
## Setting this option to an empty set includes all prefixes.
##
## For more fine-grained customization, setting this option to an
## empty set and implementing the :zeek:see:`Telemetry::log_policy`
## and :zeek:see:`Telemetry::log_policy_histogram` hooks to filter
## individual records is recommended.
option log_prefixes: set[string] = {"process", "zeek"};
## Record type used for logging counter and gauge metrics.
type Info: record {
## Timestamp of reporting.
ts: time &log;
## Peer that generated this log.
peer: string &log;
## Contains the value "counter" or "gauge" depending on
## the underlying metric type.
metric_type: string &log;
## The prefix (namespace) of the metric.
prefix: string &log;
## The name of the metric.
name: string &log;
## The unit of this metric, or unset if unit-less.
unit: string &log &optional;
## The names of the individual labels.
labels: vector of string &log;
## The values of the labels as listed in ``labels``.
label_values: vector of string &log;
## The value of this metric.
value: double &log;
};
## Record type used for logging histogram metrics.
type HistogramInfo: record {
## Timestamp of reporting.
ts: time &log;
## Peer that generated this log.
peer: string &log;
## The prefix (namespace) of the metric.
prefix: string &log;
## The name of the metric.
name: string &log;
## The unit of this metric, or unset if unit-less.
unit: string &log &optional;
## The names of the individual labels.
labels: vector of string &log;
## The values of the labels as listed in ``labels``.
label_values: vector of string &log;
## The bounds of the individual buckets
bounds: vector of double &log;
## The number of observations within each individual bucket.
values: vector of double &log;
## The sum over all observations
sum: double &log;
## The total number of observations.
observations: double &log;
};
## A default logging policy hook for the stream.
global log_policy: Log::PolicyHook;
## A default logging policy hook for the histogram stream.
global log_policy_histogram: Log::PolicyHook;
## Event triggered for every record in the stream.
global log_telemetry: event(rec: Info);
## Event triggered for every record in the histogram stream.
global log_telemetry_histogram: event(rec: HistogramInfo);
}
function do_log()
{
local ts = network_time();
local metrics = Telemetry::collect_metrics();
for ( i in metrics )
{
local m = metrics[i];
# Histograms don't have single values, skip over them.
if ( m$opts$metric_type == DOUBLE_HISTOGRAM || m$opts$metric_type == INT_HISTOGRAM )
next;
if ( |log_prefixes| > 0 && m$opts$prefix !in log_prefixes )
next;
# Render the metric_type as a short string. Unknown
# shouldn't really happen, but lets have a fallback.
local metric_type = "unknown";
switch ( m$opts$metric_type ) {
case DOUBLE_COUNTER, INT_COUNTER:
metric_type = "counter";
break;
case DOUBLE_GAUGE, INT_GAUGE:
metric_type = "gauge";
break;
}
local rec = Info($ts=ts,
$peer=peer_description,
$metric_type=metric_type,
$prefix=m$opts$prefix,
$name=m$opts$name,
$labels=m$opts$labels,
$label_values=m$labels,
$value=m$value);
if ( m$opts$unit != "1" )
rec$unit = m$opts$unit;
Log::write(LOG, rec);
}
# Logging of histograms.
ts = network_time();
local histogram_metrics = Telemetry::collect_histogram_metrics();
for ( i in histogram_metrics )
{
local hm = histogram_metrics[i];
if ( |log_prefixes| > 0 && hm$opts$prefix !in log_prefixes )
next;
local hrec = HistogramInfo($ts=ts,
$peer=peer_description,
$prefix=hm$opts$prefix,
$name=hm$opts$name,
$labels=hm$opts$labels,
$label_values=hm$labels,
$bounds=hm$opts$bounds,
$values=hm$values,
$sum=hm$sum,
$observations=hm$observations);
if ( hm$opts$unit != "1" )
hrec$unit = hm$opts$unit;
Log::write(LOG_HISTOGRAM, hrec);
}
}
event Telemetry::log()
{
# We explicitly log once during zeek_done(), so short-circuit
# here when we're already in the process of shutting down.
if ( zeek_is_terminating() )
return;
do_log();
schedule log_interval { Telemetry::log() };
}
event zeek_init() &priority=5
{
Log::create_stream(LOG, [$columns=Info, $ev=log_telemetry, $path="telemetry", $policy=log_policy]);
Log::create_stream(LOG_HISTOGRAM, [$columns=HistogramInfo, $ev=log_telemetry_histogram, $path="telemetry_histogram", $policy=log_policy_histogram]);
schedule log_interval { Telemetry::log() };
}
# Log late during zeek_done() once more. Any metric updates
# afterwards won't be visible in the log.
event zeek_done() &priority=-1000
{
do_log();
}

View file

@ -89,6 +89,10 @@ redef digest_salt = "Please change this value.";
# Extend email alerting to include hostnames
@load policy/frameworks/notice/extend-email/hostnames
# Enable logging of telemetry data into telemetry.log and
# telemetry_histogram.log.
@load frameworks/telemetry/log
# Uncomment the following line to enable detection of the heartbleed attack. Enabling
# this might impact performance a bit.
# @load policy/protocols/ssl/heartbleed

View file

@ -71,6 +71,7 @@
@load frameworks/software/version-changes.zeek
@load frameworks/software/vulnerable.zeek
@load frameworks/software/windows-version-detection.zeek
@load frameworks/telemetry/log.zeek
@load integration/barnyard2/__load__.zeek
@load integration/barnyard2/main.zeek
@load integration/barnyard2/types.zeek