Ejemplo n.º 1
0
    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)
Ejemplo n.º 2
0
    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
Ejemplo n.º 3
0
    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)
Ejemplo n.º 4
0
    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
Ejemplo n.º 5
0
    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