Modify known-services policy script to add storage framework support

This adds a flag to enable using the storage framework instead of Broker stores,
plus a btest for both broker and the the storage framework.
This commit is contained in:
Tim Wojtulewicz 2025-04-10 10:33:13 -07:00
parent 6446bdf0dc
commit 1f64bb2870
5 changed files with 154 additions and 18 deletions

View file

@ -9,6 +9,10 @@
@load base/utils/directions-and-hosts
@load base/frameworks/cluster
@load base/frameworks/storage/async
@load base/frameworks/storage/sync
@load policy/frameworks/storage/backend/sqlite
module Known;
export {
@ -39,6 +43,11 @@ export {
## operation.
const use_service_store = F &redef;
## Switches to the version of this script that uses the storage
## framework instead of Broker stores. This will default to ``T``
## in v8.1.
const use_storage_framework = F &redef;
## Require UDP server to respond before considering it an "active service".
option service_udp_requires_response = T;
@ -52,20 +61,46 @@ export {
serv: string;
};
## Storage configuration for Broker stores
## Holds the set of all known services. Keys in the store are
## :zeek:type:`Known::AddrPortServTriplet` and their associated value is
## always the boolean value of "true".
global service_store: Cluster::StoreInfo;
global service_broker_store: Cluster::StoreInfo;
## The Broker topic name to use for :zeek:see:`Known::service_store`.
## The Broker topic name to use for :zeek:see:`Known::service_broker_store`.
const service_store_name = "zeek/known/services" &redef;
## The expiry interval of new entries in :zeek:see:`Known::service_store`.
## This also changes the interval at which services get logged.
## Storage configuration for storage framework stores
## This requires setting a configuration in local.zeek that sets the
## Known::use_storage_framework boolean to T, and optionally sets different
## values in the Known::service_store_backend_options record.
## Backend to use for storing known services data using the storage framework.
global service_store_backend: opaque of Storage::BackendHandle;
## The name to use for :zeek:see:`Known::service_store_backend`. This will be used
## by the backends to differentiate tables/keys. This should be alphanumeric so
## that it can be used as the table name for the storage framework.
const service_store_prefix = "zeekknownservices" &redef;
## The type of storage backend to open.
const service_store_backend_type : Storage::Backend = Storage::STORAGE_BACKEND_SQLITE &redef;
## The options for the service store. This should be redef'd in local.zeek to set
## connection information for the backend. The options default to a memory store.
const service_store_backend_options : Storage::BackendOptions = [ $sqlite = [
$database_path=":memory:", $table_name=Known::service_store_name ]] &redef;
## The expiry interval of new entries in :zeek:see:`Known::service_broker_store`
## and :zeek:see:`Known::service_store_backend`. This also changes the interval
## at which services get logged.
const service_store_expiry = 1day &redef;
## The timeout interval to use for operations against
## :zeek:see:`Known::service_store`.
## :zeek:see:`Known::service_broker_store` and
## :zeek:see:`Known::service_store_backend`.
option service_store_timeout = 15sec;
## Tracks the set of daily-detected services for preventing the logging
@ -109,7 +144,16 @@ event zeek_init()
if ( ! Known::use_service_store )
return;
Known::service_store = Cluster::create_store(Known::service_store_name);
if ( Known::use_storage_framework )
{
local res = Storage::Sync::open_backend(Known::service_store_backend_type, Known::service_store_backend_options, Known::AddrPortServTriplet, bool);
if ( res$code == Storage::SUCCESS )
Known::service_store_backend = res$value;
else
Reporter::error(fmt("%s: Failed to open backend connection: %s", Known::service_store_prefix, res$error_str));
}
else
Known::service_broker_store = Cluster::create_store(Known::service_store_name);
}
event service_info_commit(info: ServicesInfo)
@ -123,23 +167,45 @@ event service_info_commit(info: ServicesInfo)
{
local key = AddrPortServTriplet($host = info$host, $p = info$port_num, $serv = s);
when [info, s, key] ( local r = Broker::put_unique(Known::service_store$store, key,
T, Known::service_store_expiry) )
{
if ( r$status == Broker::SUCCESS )
if ( Known::use_storage_framework )
{
when [info, s, key] ( local put_res = Storage::Async::put(Known::service_store_backend, [$key=key, $value=T, $overwrite=F,
$expire_time=Known::service_store_expiry]) )
{
if ( r$result as bool ) {
if ( put_res$code == Storage::SUCCESS )
{
info$service = set(s); # log one service at the time if multiservice
Log::write(Known::SERVICES_LOG, info);
}
else if ( put_res$code != Storage::KEY_EXISTS )
Reporter::error(fmt("%s: data store put_unique failure: %s",
Known::service_store_name, put_res$error_str));
}
timeout Known::service_store_timeout
{
Log::write(Known::SERVICES_LOG, info);
}
else
Reporter::error(fmt("%s: data store put_unique failure",
Known::service_store_name));
}
timeout Known::service_store_timeout
else
{
Log::write(Known::SERVICES_LOG, info);
when [info, s, key] ( local r = Broker::put_unique(Known::service_broker_store$store, key,
T, Known::service_store_expiry) )
{
if ( r$status == Broker::SUCCESS )
{
if ( r$result as bool ) {
info$service = set(s); # log one service at the time if multiservice
Log::write(Known::SERVICES_LOG, info);
}
}
else
Reporter::error(fmt("%s: data store put_unique failure",
Known::service_store_name));
}
timeout Known::service_store_timeout
{
Log::write(Known::SERVICES_LOG, info);
}
}
}
}
@ -155,7 +221,7 @@ event known_service_add(info: ServicesInfo)
if ( [info$host, info$port_num] !in Known::services )
Known::services[info$host, info$port_num] = set();
# service to log can be a subset of info$service if some were already seen
# service to log can be a subset of info$service if some were already seen
local info_to_log: ServicesInfo;
info_to_log$ts = info$ts;
info_to_log$host = info$host;