Attribute Selectors

Attribute selectors are how attributes (fields) are described in FSQL. They are heavily influenced by selectors in CSS and XPath, and are novel in the world of SIEMs and OCSF, especially because an FSQL attribute selector may describe one or many attributes in the schema.

As a refresher, attribute paths always have the form event[.attribute[.attribute[...]]]. Examples include authentication.user.email_addr and dns_activity.src_endpoint.ip.

FSQL attribute selectors use a dot (.) to separate parts of the expression, letting simple direct paths read just like the dot notation names commonly found in other interfaces (modifiers like / and // can also be used as separators). A few other rules: FSQL attribute selector commands begin with a colon (:), and strings with spaces must be surrounded by single quotes (). Command parameters are listed inside of parentheses, and empty parentheses are optional when parameters are not used. Commands and command aliases (like *) do not require a dot in front of them. Command names are case insensitive.

Absolute Paths

The simplest paths go directly through the schema to a single attribute by using event and attribute names – the internal OCSF/QDM name with underscores instead of space – separated by dots.

FSQL also allows captions – the label we show to humans – to be used in place of machine friendly names. Captions must be surrounded by single quotes (). Captions and names can be mixed. Example: authentication.user.’email address’.

Path Expansions

Path expansions add attributes to the selection. Names and captions are the simplest form of expansions, but a path expression can describe more than one attribute in the schema. Other expansions describe multiple paths through the schema.

ExpansionAliasesDescriptionExamples
:all*Expands to everything at the current path level. If no events have been specified in a path, the :all command will expand to all events. Otherwise, it will expand to all attributes of the selected events and any attributes specified so far.*.time *.* authentication.actor.* network_activity.*.ip
**Like :all, but always expands all paths to non-recursive ends.** #network.**
:category#Expands to all events in a given category.:category(network) #discovery #network.*.ip #findings.evidence

Expansion Modifiers

The behavior of the :all expansion can be altered with modifiers. Modifiers change the behavior of all expansions following them in the path. The short form aliases of expansion modifiers can also be substituted for the dot operator for more concise syntax.

The :!recursive modifier is enabled by default.

ModifierAliasesDescriptionExamples
:deep//Causes the :all expansion to expand to include all attributes until either the maximum depth or a recursive relationship is reached.:deep :deep.#network.* //#network.* #network//*
:shallow/The opposite of :deep, the :shallow modifier restricts expansions to just one level of the path.
:recursive+Causes expansions to follow recursive relationships. A depth limit is required. To disable recursion, use :!recursive.
:depthSets a maximum depth limit. This is required when traversing recursive relationships.:depth(4)

Path Filters

Filters narrow the list of selected paths in an attribute selector expression..

All filters can be negated with an exclamation point. For example, :!array will select all paths that are not arrays and is the logical equivalent of :scalar.

Be advised that the short form aliases will be preceded by :all with the :deep modifier temporarily enabled. This means searches like @ip_t will match every IP field in the schema.

FilterAliasesDescriptionExamples
:type@Removes all paths that do not end in an attribute of type. The type may be a primitive type or an object type, and the trailing _t may be omitted for primitive types.*.*.*.:type(ip_t) @ip_t @ip
:observable%, :entityRemoves all paths that do not end in a given observable. The observable can be specified by its caption (in quotes) or its type_id. There are also several aliases like ip that match the Query Splunk App.//*.*.:observable(2) #network//*.:observable(‘IP’) %ip
:primitiveRemoves all paths that do not end in an attribute of a primitive data type.
:objectRemoves all paths that do not end in an attribute of an object data type.
:scalarRemoves all paths that are arrays.
:arrayRemoves all paths that are scalars.
:distinctRemoves all duplicate paths.
:min_depth:minDepthRemoves all paths that are not at least n levels deep.@ip_t.:min_depth(3)
:max_depth:maxDepthRemoves all paths that are over n levels deep.@ip_t.:max_depth(7)
:deprecatedRemoves all paths to deprecated attributes.
:enumRemoves all paths that are not enumerations.
:siblingRemoves all paths that are not sibling fields. For instance, :sibling would select activity_name but not activity_id.
:group#Removes all paths to attributes that don’t match a specific group.ssh_activity.*:group(primary) ssh_activity.#primary

Transformers

Transformers modify the attribute paths in the selection.

FilterAliasesDescriptionExamples
:rootTruncates all paths to the root event.
:truncateTruncates all paths to n levels deep. This is similar to max_depth, but the number of matching paths will remain unchanged after applying truncate.@hostname_t.:truncate(5) **.:truncate(5).:distinct
:parentReplaces all paths with their parent path. Similar to .. in filesystem paths. Paths to events will not be changed.@ip_t.:parent
:primitive_parent:primitiveParentReplaces all paths to primitive type attributes with their parent object or event. For instance, network_activity.dst_endpoint.ip will be replaced with network_activity.dst_endpoint, but authentication.actor will not be changed.

Set Operations

Partial attribute selectors can be combined with set operations and grouped with parentheses.

Some examples:
network_activity.(* - (start_time | end_time)) (network_activity.* | dns_activity.*) #network - dns_activity

Set OperatorNameDescription
``Union (or)`AB` selects all paths from both A and B.
&Intersection (and)A & B selects all paths from A that are also in B.
-Difference (minus)A - B selects all paths from A that are not in B.