Documentation
¶
Index ¶
- Constants
- Variables
- func ExprString(e Expr) string
- func GetEventTypeFromConditions(r *ParseResult) string
- func HasComplexWhereConditions(r *ParseResult) bool
- func HasUnmappedComputedFields(r *ParseResult) bool
- func IsStatisticalQuery(r *ParseResult) bool
- func MaxSpanDuration(span string) (int64, bool)
- func NormalizeQuery(query string) string
- type BadExpr
- type Binary
- type Call
- type Condition
- type EventQuery
- type ExpectedCondition
- type Expr
- type Field
- type FieldProvenance
- type FieldUsage
- type GeneratedCase
- type InExpr
- type Lineage
- type Literal
- type LiteralKind
- type Not
- type Paren
- type ParseResult
- type PathSeg
- type PatternExpr
- type PatternKind
- type Pipe
- type PipeInfo
- type Query
- type QueryBody
- type Sequence
- type SequenceInfo
- type SequenceKind
- type SequenceStep
- type SequenceStepInfo
- type Token
- type TokenType
- type Unary
Constants ¶
const MaxInputSize = 1 << 20 // 1 MiB
MaxInputSize is the largest query Parse and ExtractConditions accept.
Variables ¶
var ErrEmptyQuery = errors.New("empty query")
ErrEmptyQuery is returned when the input contains no tokens.
var ErrInputTooLarge = errors.New("input exceeds maximum size")
ErrInputTooLarge is returned when the input exceeds MaxInputSize.
var MaxParseTime = 5 * time.Second
MaxParseTime is the maximum time allowed for parsing a single query. Queries that exceed it return an error result instead of hanging.
Functions ¶
func ExprString ¶
ExprString renders any expression node as canonical EQL text.
func GetEventTypeFromConditions ¶
func GetEventTypeFromConditions(r *ParseResult) string
GetEventTypeFromConditions derives a canonical event-type string (e.g. "windows_4688", "sysmon_1") from an event-code condition, so EQL rules classify identically to the Sigma/SPL/KQL rules for the same telemetry. Returns "" when the query carries no recognizable event code.
func HasComplexWhereConditions ¶
func HasComplexWhereConditions(r *ParseResult) bool
HasComplexWhereConditions reports whether any extracted condition uses a pattern/list/function operator rather than plain comparison. Mirrors the sibling helper.
func HasUnmappedComputedFields ¶
func HasUnmappedComputedFields(r *ParseResult) bool
HasUnmappedComputedFields reports whether the query defines computed fields that are not backed by a source field. EQL has no computed-field construct (no eval/extend/project), so this is always false; it exists for uniform API parity with the sibling parsers.
func IsStatisticalQuery ¶
func IsStatisticalQuery(r *ParseResult) bool
IsStatisticalQuery reports whether the query aggregates or correlates rather than simply filtering: it uses a counting/uniquing pipe, or is a sequence/sample (stateful correlation). Mirrors the sibling helper.
func MaxSpanDuration ¶
MaxSpanDuration converts a maxspan value like "30s" or "2h" to milliseconds. Returns false when the text is not a recognized duration.
func NormalizeQuery ¶
NormalizeQuery cleans up EQL text that was pasted from documents, extracted from JSON/YAML/TOML rule files, or otherwise mangled in transit, without changing the meaning of well-formed queries. ExtractConditions applies it automatically; Parse does not.
Types ¶
type BadExpr ¶
type BadExpr struct {
Near string
}
BadExpr is a placeholder emitted during error recovery.
type Binary ¶
Binary covers logical (and/or), comparison (== != < <= > >= : treated separately), and arithmetic (+ - * / %) operators. Op is the canonical lowercase operator text.
type Condition ¶
type Condition struct {
Field string `json:"field"`
Operator string `json:"operator"` // "==", "!=", "<", "<=", ">", ">=", ":", "like", "regex", "in", or a function name ("wildcard", "cidrmatch", ...)
Value string `json:"value"`
Negated bool `json:"negated"`
CaseInsensitive bool `json:"case_insensitive,omitempty"` // : operator, ~ variants
LogicalOp string `json:"logical_op"` // "AND" or "OR" connecting to the previous condition
Alternatives []string `json:"alternatives,omitempty"` // all values for list operators and merged same-field ORs
EventCategory string `json:"event_category,omitempty"` // category of the event filter this came from ("any" or "" for bare)
SequenceStep int `json:"sequence_step"` // 0-based step index; 0 for non-sequence queries
FromUntil bool `json:"from_until,omitempty"` // condition came from an until clause
FromMissing bool `json:"from_missing,omitempty"` // condition came from a ![ missing-event clause
PipeStage int `json:"pipe_stage"` // 0 = main query, N = Nth pipe (1-based, filter pipes)
IsOptional bool `json:"is_optional,omitempty"` // field carried the ? optional marker
Function string `json:"function,omitempty"` // function wrapping the field, e.g. "length" in length(f) > 5
ValueIsField bool `json:"value_is_field,omitempty"` // Value names another field (field-to-field comparison)
CoFields []string `json:"co_fields,omitempty"` // other fields in the same comparison (e.g. b in "a + b > 10")
Lineage string `json:"lineage,omitempty"` // "child", "descendant", "event" for legacy lineage subqueries
}
Condition is one field predicate extracted from an EQL query.
func DeduplicateConditions ¶
DeduplicateConditions removes duplicate conditions, keeping the first occurrence of each. Two conditions are duplicates when they agree on field, operator, value, negation, case-sensitivity, alternatives, and correlation context (step, pipe stage, until, lineage). Exported for parity with the sibling parsers' adapters.
type EventQuery ¶
type EventQuery struct {
Category string // literal category text ("" when Any or Bare)
CategoryAny bool // `any where ...`
Bare bool // no `category where` prefix, just an expression
Where Expr
}
EventQuery is `category where condition`, `any where condition`, or — as a tolerated extension for extraction of stored rule fragments — a bare boolean expression without a category (Bare=true).
type ExpectedCondition ¶
type ExpectedCondition struct {
Field string `json:"field"`
Operator string `json:"operator"`
Value string `json:"value,omitempty"`
Alternatives []string `json:"alternatives,omitempty"`
Negated bool `json:"negated,omitempty"`
SequenceStep int `json:"sequence_step,omitempty"`
}
ExpectedCondition is a condition signature used for differential testing. It captures the fields the generator can predict deterministically.
type Expr ¶
type Expr interface {
// contains filtered or unexported methods
}
Expr is the interface implemented by all expression nodes.
func ParseExpression ¶
ParseExpression parses a standalone boolean expression (no event category, sequences, or pipes).
type Field ¶
Field is a (possibly optional, possibly indexed) field reference such as `?process.args[0]` or “ `host-name`.ip “.
type FieldProvenance ¶
type FieldProvenance string
FieldProvenance indicates where a field originates relative to a query's correlation structure. The string values match the sibling parsers' provenance vocabulary (main/joined/join_key/ambiguous) so a platform adapter can treat EQL uniformly with KQL/SPL; ProvenanceUnknown is an EQL addition for a field absent from the result.
const ( // ProvenanceMain is a field filtering the primary event stream (a // non-sequence query, the first sequence step, or a filter pipe). ProvenanceMain FieldProvenance = "main" // ProvenanceJoined is a field from a correlated event — a later sequence // step or an until clause. ProvenanceJoined FieldProvenance = "joined" // ProvenanceJoinKey is a field used as a correlation key (a `by` clause). ProvenanceJoinKey FieldProvenance = "join_key" // ProvenanceAmbiguous is a field used in more than one distinct role. ProvenanceAmbiguous FieldProvenance = "ambiguous" // ProvenanceUnknown is returned for a field not present in the result. ProvenanceUnknown FieldProvenance = "unknown" )
func ClassifyFieldProvenance ¶
func ClassifyFieldProvenance(r *ParseResult, field string) FieldProvenance
ClassifyFieldProvenance reports the role a field plays in the parsed query, using the same vocabulary as the sibling parsers: a correlation key (join_key), a primary-stream filter (main), a correlated-event filter (joined), or several roles at once (ambiguous). A field the query never references is ProvenanceUnknown.
type FieldUsage ¶
type FieldUsage struct {
IsJoinKey bool `json:"is_join_key"`
Steps []int `json:"steps,omitempty"` // sequence steps referencing the field
InPipes bool `json:"in_pipes"`
InUntil bool `json:"in_until"`
}
FieldUsage classifies how a field participates in a query.
func ClassifyFieldUsage ¶
func ClassifyFieldUsage(r *ParseResult, field string) FieldUsage
ClassifyFieldUsage reports how a field participates in the parsed query.
type GeneratedCase ¶
type GeneratedCase struct {
ID int64 `json:"id"`
Seed int64 `json:"seed"`
Query string `json:"query"`
Expected []ExpectedCondition `json:"expected"`
}
GeneratedCase is one entry in the generated differential corpus: a rendered query plus the conditions a correct extractor must produce.
type Lineage ¶
type Lineage struct {
Kind string // "child", "descendant", "event"
Sub *EventQuery
}
Lineage is the legacy Endgame relationship predicate: `child of [process where ...]`, `descendant of [...]`, `event of [...]`.
type Literal ¶
type Literal struct {
Kind LiteralKind
Value string // decoded string value
Text string // raw number text
Bool bool
Raw bool // originated from a raw string form
}
Literal is a constant value. For strings, Value holds the decoded text; for numbers, Text holds the original notation.
type LiteralKind ¶
type LiteralKind int
LiteralKind discriminates literal values.
const ( LitString LiteralKind = iota LitNumber LitBool LitNull )
type ParseResult ¶
type ParseResult struct {
Conditions []Condition `json:"conditions"`
EventCategories []string `json:"event_categories,omitempty"` // unique categories in source order
Sequence *SequenceInfo `json:"sequence,omitempty"` // set for sequence/join/sample queries
Pipes []PipeInfo `json:"pipes,omitempty"`
Commands []string `json:"commands,omitempty"` // construct kind + pipe names, in order
Fields []string `json:"fields,omitempty"` // every field referenced anywhere (source order, deduped)
JoinKeys []string `json:"join_keys,omitempty"` // every by-clause field (global + per-step)
Errors []string `json:"errors,omitempty"`
}
ParseResult contains everything extracted from a query.
func ExtractConditions ¶
func ExtractConditions(query string) *ParseResult
ExtractConditions parses an EQL query and extracts conditions, correlation structure, pipes, and referenced fields. It never panics and never hangs: hostile input yields a result whose Errors explains what went wrong. Input is normalized with NormalizeQuery first.
func (*ParseResult) GroupByFields ¶
func (r *ParseResult) GroupByFields() []string
GroupByFields returns the query's correlation keys (the `by` clause fields), under the name the sibling parsers use for their grouping axis. It is an alias for the JoinKeys field, provided for uniform adapter code.
type PatternExpr ¶
type PatternExpr struct {
Kind PatternKind
X Expr
Patterns []Expr
Parenthesized bool // list form was written with parentheses
Insensitive bool
}
PatternExpr is `x : v`, `x like v`, `x regex v`, or their list forms `x like ("a*", "b*")`. Insensitive marks the ~ variants (":" is inherently case-insensitive and keeps Insensitive=false).
type PatternKind ¶
type PatternKind string
PatternKind distinguishes the string-matching predicates.
const ( PatternSeq PatternKind = ":" // case-insensitive equality with wildcards PatternLike PatternKind = "like" // wildcard match PatternRegex PatternKind = "regex" // regular expression match )
type Query ¶
Query is a parsed EQL statement: one body (event query, sequence, join, or sample) followed by zero or more pipes.
func Parse ¶
Parse parses a single EQL statement and returns its AST. The parser is tolerant: it recovers from many errors and still produces a partial AST, but any problem encountered is reported in the returned error (the AST is still valid to inspect). Input is parsed as-is; use NormalizeQuery first for content pasted from documents.
type QueryBody ¶
type QueryBody interface {
// contains filtered or unexported methods
}
QueryBody is implemented by *EventQuery and *Sequence.
type Sequence ¶
type Sequence struct {
Kind SequenceKind
By []Expr // global join keys (sequence/join/sample `by`)
MaxSpan string // raw duration text, e.g. "30s" ("" when absent)
WithByOrder bool // header was written `with maxspan=... by ...` (parsed-then-tolerated order)
Steps []*SequenceStep
Until *SequenceStep
}
Sequence is `sequence ...`, `join ...`, or `sample ...`.
type SequenceInfo ¶
type SequenceInfo struct {
Kind string `json:"kind"` // "sequence", "join", "sample"
MaxSpan string `json:"max_span,omitempty"`
MaxSpanMS int64 `json:"max_span_ms,omitempty"`
ByFields []string `json:"by_fields,omitempty"` // global join keys
Steps []SequenceStepInfo `json:"steps"`
Until *SequenceStepInfo `json:"until,omitempty"`
}
SequenceInfo describes the correlation structure of a sequence, join, or sample query — the EQL analog of join metadata in the other parsers.
type SequenceKind ¶
type SequenceKind string
SequenceKind discriminates the three correlation constructs that share the Sequence node shape.
const ( KindSequence SequenceKind = "sequence" KindJoin SequenceKind = "join" KindSample SequenceKind = "sample" )
type SequenceStep ¶
type SequenceStep struct {
Missing bool // opened with ![ — matches the absence of the event
Query *EventQuery
By []Expr // per-step join keys
Runs int // `with runs=N`, 0 when absent
WithKey string // raw key of a `with key=value` modifier ("runs" normally)
}
SequenceStep is one bracketed term of a sequence/join/sample.
type SequenceStepInfo ¶
type SequenceStepInfo struct {
EventCategory string `json:"event_category"`
ByFields []string `json:"by_fields,omitempty"`
Runs int `json:"runs,omitempty"`
Missing bool `json:"missing,omitempty"`
ConditionCount int `json:"condition_count"`
Subquery *ParseResult `json:"subquery,omitempty"`
}
SequenceStepInfo describes one bracketed event of a sequence/join/sample. Subquery holds a self-contained recursive extraction of the step's event filter (`[category where ...]`), the EQL analog of a join subsearch — its conditions are step-relative (SequenceStep 0) and independently inspectable.
type Token ¶
type Token struct {
Type TokenType
Text string // raw source text (original spelling)
Value string // decoded value for strings and backtick identifiers, lowercase-insensitive-normalized for keywords
Pos int // byte offset in input
Line int // 1-based line
Col int // 1-based column (bytes)
Tilde bool // identifier carried a ~ suffix (case-insensitive function)
Raw bool // string was raw (triple-quoted or ?"..." form)
TripleQuoted bool // string used """..."""
SingleQuoted bool // string used '...' (legacy Endgame form)
}
Token is a single lexical unit with position information.
type TokenType ¶
type TokenType int
TokenType identifies the lexical class of a token.
const ( TokenEOF TokenType = iota TokenError // Literals and names TokenIdent // process, endsWith, endsWith~ (Tilde=true) TokenBacktickIdent // `my-field` (Value holds the unescaped name) TokenString // "...", """...""", '...', ?"..." (Value holds the decoded value) TokenNumber // 42, 3.14, 1e-5, .5 // Keywords TokenAnd TokenOr TokenNot TokenIn // in TokenInTilde // in~ TokenLike // like TokenLikeTilde // like~ TokenRegex // regex TokenRegexTilde // regex~ TokenWhere TokenSequence TokenJoin TokenSample TokenUntil TokenBy TokenWith TokenMaxspan TokenOf TokenAny TokenTrue TokenFalse TokenNull // Operators and punctuation TokenEQ // == TokenNEQ // != TokenLT // < TokenLTE // <= TokenGT // > TokenGTE // >= TokenColon // : TokenAssign // = TokenPlus // + TokenMinus // - TokenStar // * TokenSlash // / TokenPercent // % TokenPipe // | TokenComma // , TokenLParen // ( TokenRParen // ) TokenLBrack // [ TokenRBrack // ] TokenMissing // ![ (missing-event subquery opener) TokenDot // . TokenOptional // ? (optional field marker) )