zeek/scripts/policy/frameworks/management/request.zeek
Josh Soref 21e0d777b3 Spelling fixes: scripts
* accessing
* across
* adding
* additional
* addresses
* afterwards
* analyzer
* ancillary
* answer
* associated
* attempts
* because
* belonging
* buffer
* cleanup
* committed
* connects
* database
* destination
* destroy
* distinguished
* encoded
* entries
* entry
* hopefully
* image
* include
* incorrect
* information
* initial
* initiate
* interval
* into
* java
* negotiation
* nodes
* nonexistent
* ntlm
* occasional
* omitted
* otherwise
* ourselves
* paragraphs
* particular
* perform
* received
* receiver
* referring
* release
* repetitions
* request
* responded
* retrieval
* running
* search
* separate
* separator
* should
* synchronization
* target
* that
* the
* threshold
* timeout
* transaction
* transferred
* transmission
* triggered
* vetoes
* virtual

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2022-11-02 17:36:39 -04:00

168 lines
5.2 KiB
Text

##! This module implements a request state abstraction in the Management
##! framework that both controller and agent use to connect request events to
##! subsequent response ones, and to be able to time out such requests.
@load ./config
@load ./types
module Management::Request;
export {
## Request records track state associated with a request/response event
## pair. Calls to
## :zeek:see:`Management::Request::create` establish such state
## when an entity sends off a request event, while
## :zeek:see:`Management::Request::finish` clears the state when
## a corresponding response event comes in, or the state times out.
type Request: record {
## Each request has a hopefully unique ID provided by the requester.
id: string;
## For requests that result based upon another request (such as when
## the controller sends requests to agents based on a request it
## received by the client), this specifies that original, "parent"
## request.
parent_id: string &optional;
## The results vector builds up the list of results we eventually
## send to the requestor when we have processed the request.
results: Management::ResultVec &default=vector();
## An internal flag to track whether a request is complete.
finished: bool &default=F;
};
# To allow a callback to refer to Requests, the Request type must
# exist. So redef to add it:
redef record Request += {
## A callback to invoke when this request is finished via
## :zeek:see:`Management::Request::finish`.
finish: function(req: Management::Request::Request) &optional;
};
## The timeout interval for request state. Such state (see the
## :zeek:see:`Management::Request` module) ties together request and
## response event pairs. A timeout causes cleanup of request state if
## regular request/response processing hasn't already done so. It
## applies both to request state kept in the controller and the agent,
## though the two use different timeout values: agent-side requests time
## out more quickly. This allows agents to send more meaningful error
## messages, while the controller's timeouts serve as a last resort to
## ensure response to the client.
const timeout_interval = 10sec &redef;
## A token request that serves as a null/nonexistent request.
global null_req = Request($id="", $finished=T);
## This function establishes request state.
##
## reqid: the identifier to use for the request.
##
global create: function(reqid: string &default=unique_id("")): Request;
## This function looks up the request for a given request ID and returns
## it. When no such request exists, returns Management::Request::null_req.
##
## reqid: the ID of the request state to retrieve.
##
global lookup: function(reqid: string): Request;
## This function marks a request as complete and causes Zeek to release
## its internal state. When the request does not exist, this does
## nothing.
##
## reqid: the ID of the request state to release.
##
global finish: function(reqid: string): bool;
## This event fires when a request times out (as per the
## Management::Request::timeout_interval) before it has been finished via
## Management::Request::finish().
##
## req: the request state that is expiring.
##
global request_expired: event(req: Request);
## This function is a helper predicate to indicate whether a given
## request is null.
##
## request: a Request record to check.
##
## Returns: T if the given request matches the null_req instance, F otherwise.
##
global is_null: function(request: Request): bool;
## For troubleshooting, this function renders a request record to a string.
##
## request: the request to render.
##
global to_string: function(request: Request): string;
}
function requests_expire_func(reqs: table[string] of Request, reqid: string): interval
{
# No need to flag request expiration when we've already internally marked
# the request as done.
if ( ! reqs[reqid]$finished )
event Management::Request::request_expired(reqs[reqid]);
return 0secs;
}
# This is the global request-tracking table. The table maps from request ID
# strings to corresponding Request records. Entries time out after the
# Management::Request::timeout_interval. Upon expiration, a request_expired
# event triggers that conveys the request state.
global g_requests: table[string] of Request
&create_expire=timeout_interval &expire_func=requests_expire_func;
function create(reqid: string): Request
{
local ret = Request($id=reqid);
g_requests[reqid] = ret;
return ret;
}
function lookup(reqid: string): Request
{
if ( reqid in g_requests )
return g_requests[reqid];
return null_req;
}
function finish(reqid: string): bool
{
if ( reqid !in g_requests )
return F;
local req = g_requests[reqid];
delete g_requests[reqid];
if ( req?$finish )
req$finish(req);
req$finished = T;
return T;
}
function is_null(request: Request): bool
{
if ( request$id == "" )
return T;
return F;
}
function to_string(request: Request): string
{
local parent_id = "";
if ( request?$parent_id )
parent_id = fmt(" (via %s)", request$parent_id);
return fmt("[request %s%s %s, results: %s]", request$id, parent_id,
request$finished ? "finished" : "pending",
Management::result_vec_to_string(request$results));
}