1"""`BestChecker`."""
2
3import logging
4
5import idstools.rule
6
7from suricata_check.checkers.interface import CheckerInterface
8from suricata_check.utils.checker import (
9 get_rule_option,
10 is_rule_option_set,
11 is_rule_suboption_set,
12)
13from suricata_check.utils.checker_typing import ISSUES_TYPE, Issue
14
15
[docs]
16class BestChecker(CheckerInterface):
17 """The `BestChecker` contains several checks for best practices to improve the experience of Suricata rules for everyone.
18
19 Codes C100-C110 report on missing fields that should be set.
20 """
21
22 codes = {
23 "C100": {"severity": logging.INFO},
24 "C101": {"severity": logging.INFO},
25 "C102": {"severity": logging.INFO},
26 }
27
28 def _check_rule(
29 self: "BestChecker",
30 rule: idstools.rule.Rule,
31 ) -> ISSUES_TYPE:
32 issues: ISSUES_TYPE = []
33
34 if not (
35 is_rule_option_set(rule, "noalert")
36 or is_rule_suboption_set(rule, "flowbits", "noalert")
37 ) and not is_rule_option_set(rule, "target"):
38 issues.append(
39 Issue(
40 code="C100",
41 message="""\
42The rule does not use the `target` Suricata meta option.
43Consider adding the `target` option to specify which IP address is the target of the attack.\
44""",
45 ),
46 )
47
48 if not is_rule_suboption_set(rule, "metadata", "created_at"):
49 issues.append(
50 Issue(
51 code="C101",
52 message="""\
53The rule does not use set the `created_at` metadata option.
54Consider adding the `created_at` metadata option to inform users of the recency of this signature.\
55""",
56 ),
57 )
58
59 if (
60 is_rule_option_set(rule, "rev")
61 and int(get_rule_option(rule, "rev")) > 1 # type: ignore reportArgumentType
62 and not is_rule_suboption_set(rule, "metadata", "updated_at")
63 ):
64 issues.append(
65 Issue(
66 code="C102",
67 message="""\
68The rule does not use set the `updated_at` metadata option while it has been revised since creation.
69Consider adding the `updated_at` metadata option to inform users of the recency of this signature.\
70""",
71 ),
72 )
73
74 return issues