def _validate_kql(ecs_versions, beats_version, indexes, query, name): # validate against all specified schemas or the latest if none specified parsed = kql.parse(query) beat_types = [index.split("-")[0] for index in indexes if "beat-*" in index] beat_schema = beats.get_schema_from_kql(parsed, beat_types, version=beats_version) if beat_types else None if not ecs_versions: kql.parse(query, schema=ecs.get_kql_schema(indexes=indexes, beat_schema=beat_schema)) else: for version in ecs_versions: try: schema = ecs.get_kql_schema(version=version, indexes=indexes, beat_schema=beat_schema) except KeyError: raise KeyError( 'Unknown ecs schema version: {} in rule {}.\n' 'Do you need to update schemas?'.format(version, name)) try: kql.parse(query, schema=schema) except kql.KqlParseError as exc: message = exc.error_msg trailer = None if "Unknown field" in message and beat_types: trailer = "\nTry adding event.module or event.dataset to specify beats module" raise kql.KqlParseError(exc.error_msg, exc.line, exc.column, exc.source, len(exc.caret.lstrip()), trailer=trailer)
def validate_query(self, beats_version: str, ecs_versions: List[str]): """Static method to validate the query, called from the parent which contains [metadata] information.""" indexes = self.index or [] parsed = self.parsed_query beat_types = [ index.split("-")[0] for index in indexes if "beat-*" in index ] beat_schema = beats.get_schema_from_kql( parsed, beat_types, version=beats_version) if beat_types else None if not ecs_versions: kql.parse(self.query, schema=ecs.get_kql_schema(indexes=indexes, beat_schema=beat_schema)) else: for version in ecs_versions: schema = ecs.get_kql_schema(version=version, indexes=indexes, beat_schema=beat_schema) try: kql.parse(self.query, schema=schema) except kql.KqlParseError as exc: message = exc.error_msg trailer = None if "Unknown field" in message and beat_types: trailer = "\nTry adding event.module or event.dataset to specify beats module" raise kql.KqlParseError(exc.error_msg, exc.line, exc.column, exc.source, len(exc.caret.lstrip()), trailer=trailer) from None
def validate(self, as_rule=False, versioned=False): """Validate against a rule schema, query schema, and linting.""" self.normalize() if as_rule: schema_validate(self.rule_format(), as_rule=True) else: schema_validate(self.contents, versioned=versioned) if self.query and self.contents['language'] == 'kuery': # validate against all specified schemas or the latest if none specified ecs_versions = self.metadata.get('ecs_version') indexes = self.contents.get("index", []) beat_types = [ index.split("-")[0] for index in indexes if "beat-*" in index ] beat_schema = beats.get_schema_for_query( self.parsed_kql, beat_types) if beat_types else None if not ecs_versions: kql.parse(self.query, schema=ecs.get_kql_schema(indexes=indexes, beat_schema=beat_schema)) else: for version in ecs_versions: try: schema = ecs.get_kql_schema(version=version, indexes=indexes, beat_schema=beat_schema) except KeyError: raise KeyError( 'Unknown ecs schema version: {} in rule {}.\n' 'Do you need to update schemas?'.format( version, self.name)) try: kql.parse(self.query, schema=schema) except kql.KqlParseError as exc: message = exc.error_msg trailer = None if "Unknown field" in message and beat_types: trailer = "\nTry adding event.module and event.dataset to specify beats module" raise kql.KqlParseError(exc.error_msg, exc.line, exc.column, exc.source, len(exc.caret.lstrip()), trailer=trailer)
def validate(self, data: QueryRuleData, meta: RuleMeta) -> None: """Static method to validate the query, called from the parent which contains [metadata] information.""" ast = self.ast if meta.query_schema_validation is False or meta.maturity == "deprecated": # syntax only, which is done via self.ast return indexes = data.index or [] beats_version = meta.beats_version or beats.get_max_version() ecs_versions = meta.ecs_versions or [ecs.get_max_version()] beat_types = [ index.split("-")[0] for index in indexes if "beat-*" in index ] beat_schema = beats.get_schema_from_kql( ast, beat_types, version=beats_version) if beat_types else None if not ecs_versions: kql.parse(self.query, schema=ecs.get_kql_schema(indexes=indexes, beat_schema=beat_schema)) else: for version in ecs_versions: schema = ecs.get_kql_schema(version=version, indexes=indexes, beat_schema=beat_schema) try: kql.parse(self.query, schema=schema) except kql.KqlParseError as exc: message = exc.error_msg trailer = None if "Unknown field" in message and beat_types: trailer = "\nTry adding event.module or event.dataset to specify beats module" raise kql.KqlParseError(exc.error_msg, exc.line, exc.column, exc.source, len(exc.caret.lstrip()), trailer=trailer) from None
def validate(self, data: QueryRuleData, meta: RuleMeta) -> None: """Static method to validate the query, called from the parent which contains [metadata] information.""" ast = self.ast if meta.query_schema_validation is False or meta.maturity == "deprecated": # syntax only, which is done via self.ast return for stack_version, mapping in meta.get_validation_stack_versions( ).items(): beats_version = mapping['beats'] ecs_version = mapping['ecs'] err_trailer = f'stack: {stack_version}, beats: {beats_version}, ecs: {ecs_version}' beat_types = beats.parse_beats_from_index(data.index) beat_schema = beats.get_schema_from_kql( ast, beat_types, version=beats_version) if beat_types else None schema = ecs.get_kql_schema(version=ecs_version, indexes=data.index or [], beat_schema=beat_schema) try: kql.parse(self.query, schema=schema) except kql.KqlParseError as exc: message = exc.error_msg trailer = err_trailer if "Unknown field" in message and beat_types: trailer = f"\nTry adding event.module or event.dataset to specify beats module\n\n{trailer}" raise kql.KqlParseError(exc.error_msg, exc.line, exc.column, exc.source, len(exc.caret.lstrip()), trailer=trailer) from None except Exception: print(err_trailer) raise