Query Language

VAST features a declarative query language for extracting a subset of the data.

Expressions

A query in VAST is a boolean expression, consisting of conjunctions (&&), disjunctions (||), and negations (!). The operands of these operations are either predicates or further sub-expressions.

For example, for valid predicates A, B, C, and D, an expression could be A && B && (C || !D). This expression is equivalent to the following parse tree:

graph TB; con0(&&) --> A con0(&&) --> con1(&&) con1 --> B con1 --> dis("||") dis --> C dis --> neg(!) neg --> D classDef node fill:#78d400,stroke:#00334d; classDef edgePath stroke:#00334d;

Predicates

A predicate has the form LHS op RHS, where LHS denotes the left-hand side operand and RHS the right-hand side operand. The relational operator op defines which operand types are compatible with each other. An operand is either an extractor or data.

Operators

  1. <
  2. <=
  3. >=
  4. ==
  5. !=
  6. in
  7. !in
  8. ni
  9. !ni
  10. ~
  11. !~

Extractors

An extractor retrieves a certain aspect of an event. VAST supports the following extractor types:

  1. Attribute: matches fields that have a particular attribute value.

  2. Type: extracts all event types that have a field of a given type.

  3. Key: extracts all fields whose name match a given record field name.

Examples
  • #type == "zeek.conn"
  • #timestamp > 2 days ago

Attribute Extractor

Attribute extractors have the form #x where x is the name of an attribute.

For example, #timestamp extracts the event timestamp and requires an operand of type time. A predicate with a #timestamp extractor only considers event types that have a field with the #timestamp attribute.

Type Extractor

Type extractors have the form :T where T is the type of a field.

VAST supports the following type extractors:

  • :bool
  • :count
  • :int
  • :real
  • :duration
  • :time
  • :string
  • :pattern
  • :addr
  • :subnet
  • :port
Examples
  • :addr == 6.6.6.6
  • :count > 42M
  • "evil" in :string

Some predicates invovling type extractors and equality operators can be written rather tersely. These data predicates have the form :T == X, where X is a data instance and T the type of X. For such configurations, the predicate parser also accepts X as stand-alone predicate and infers T automatically. For example, 6.6.6.6 is a valid predicate and internally expands to :addr == 6.6.6.6. This allows for quick equality searches, such as (6.6.6.6 || 80/tcp) && "evil".

Key Extractor

Key extractors have the form x or x.y.z where x, y, and z match on field names. The dot allows for accessing fields in nested records.

A key extractor is always a suffix. If you want the nested field z you can omit x.y, it suffices to write just z.

Examples
  • ts > 1 day ago
  • id.orig_h in 192.168.0.0/24
  • orig_bytes >= 10Ki