def test_equivalent(name, expression, alternate): """Check that two expressions parse to the same AST.""" with eql.parser.skip_optimizations: source_ast = eql.parse_expression(expression) dest_ast = eql.parse_expression(alternate) assert source_ast == dest_ast
def test_optimizer(name, unoptimized, optimized): """Check that optimization rules are working as expected.""" with eql.parser.skip_optimizations: unoptimized_ast = eql.parse_expression(unoptimized) optimized_ast = eql.parse_expression(optimized) assert unoptimized_ast != optimized_ast assert unoptimized_ast.optimize(recursive=True) == optimized_ast
def __init__(self, config): """Create the normalizer.""" object.__init__(self) self.config = config self.strict = config['strict'] self.domain = config['domain'] self.name = config['name'] self.time_field = config['timestamp']['field'] self.time_format = config['timestamp']['format'] # Parse out the EQL field mapping with eql.ParserConfig(custom_functions=extra_functions.values()): self.field_mapping = { field: eql.parse_expression(eql_text) for field, eql_text in self.config.get('fields', {}).get( 'mapping', {}).items() } # Parse out the EQL event types self.event_filters = OrderedDict() self.event_enums = OrderedDict() self.event_field_mapping = OrderedDict() for event_name, event_config in self.config.get('events', {}).items(): self.event_filters[event_name] = eql.parse_expression( event_config['filter']) self.event_enums[event_name] = OrderedDict() self.event_field_mapping[event_name] = OrderedDict() # Create a lookup for all of the event fields for field_name, mapped_expression in event_config.get( 'mapping', {}).items(): self.event_field_mapping[event_name][ field_name] = eql.parse_expression(mapped_expression) # Now loop over all of the enums, and build a mapping for EQL for field_name, enum_mapping in event_config.get('enum', {}).items(): self.event_enums[event_name][field_name] = OrderedDict() for enum_option, enum_expr in enum_mapping.items(): self.event_enums[event_name][field_name][ enum_option] = eql.parse_expression(enum_expr) self._current_event_type = None self.data_normalizer = self.get_data_normalizer() self.query_normalizer = QueryNormalizer(self)
def from_eql(tree, optimize=True): if not isinstance(tree, eql.ast.EqlNode): try: tree = eql.parse_query(tree, implied_any=True) except eql.EqlSemanticError: tree = eql.parse_expression(tree) converted = Eql2Kql().walk(tree) return converted.optimize(recursive=True) if optimize else converted
def test_fold(name, text, expected, case_sensitive): """Check that expressions fold and evaluate correctly.""" with case_sensitivity(case_sensitive): with eql.parser.skip_optimizations: parsed = eql.parse_expression(text) assert not isinstance(parsed, eql.ast.Literal) assert engine_eval(parsed) == expected assert parsed.fold() == expected
def get_scoper(self): """Get a nested object for an EQL field.""" scope = self.config.get('fields', {}).get('scope') if scope is None: return field = eql.parse_expression(scope) # type: Field keys = [field.base] + field.path def walk_path(value): for key in keys: if value is None: break elif isinstance(value, dict): value = value.get(key) elif key < len(value): value = value[key] else: value = None return value or {} return walk_path
def validate(self, kql_source, eql_source, schema=None): self.assertEqual(kql.to_eql(kql_source, schema=schema), eql.parse_expression(eql_source))
def test_verifier(name, text): """Check that invalid function signatures are correctly detected.""" with pytest.raises(eql.EqlSemanticError): eql.parse_expression(text)