1"""`BestChecker`."""
2
3import logging
4from types import MappingProxyType
5
6from suricata_check.checkers.interface import CheckerInterface
7from suricata_check.utils.checker import (
8 get_rule_option,
9 is_rule_option_set,
10 is_rule_suboption_set,
11)
12from suricata_check.utils.checker_typing import ISSUES_TYPE, Issue
13from suricata_check.utils.rule import Rule
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 = MappingProxyType(
23 {
24 "C100": {"severity": logging.INFO},
25 "C101": {"severity": logging.INFO},
26 "C102": {"severity": logging.INFO},
27 "C103": {"severity": logging.INFO},
28 },
29 )
30
31 def _check_rule(
32 self: "BestChecker",
33 rule: Rule,
34 ) -> ISSUES_TYPE:
35 issues: ISSUES_TYPE = []
36
37 if not (
38 is_rule_option_set(rule, "noalert")
39 or is_rule_suboption_set(rule, "flowbits", "noalert")
40 ) and not is_rule_option_set(rule, "target"):
41 issues.append(
42 Issue(
43 code="C100",
44 message="""\
45The rule does not use the `target` Suricata meta option.
46Consider adding the `target` option to specify which IP address is the target of the attack.\
47""",
48 ),
49 )
50
51 if not is_rule_suboption_set(rule, "metadata", "created_at"):
52 issues.append(
53 Issue(
54 code="C101",
55 message="""\
56The rule does not use set the `created_at` metadata option.
57Consider adding the `created_at` metadata option to inform users of the recency of this signature.\
58""",
59 ),
60 )
61
62 if (
63 is_rule_option_set(rule, "rev")
64 and int(get_rule_option(rule, "rev")) > 1 # type: ignore reportArgumentType
65 and not is_rule_suboption_set(rule, "metadata", "updated_at")
66 ):
67 issues.append(
68 Issue(
69 code="C102",
70 message="""\
71The rule does not use set the `updated_at` metadata option while it has been revised since creation.
72Consider adding the `updated_at` metadata option to inform users of the recency of this signature.\
73""",
74 ),
75 )
76
77 if not (
78 is_rule_option_set(rule, "noalert")
79 or is_rule_suboption_set(rule, "flowbits", "noalert")
80 ) and not is_rule_option_set(rule, "classtype"):
81 issues.append(
82 Issue(
83 code="C103",
84 message="""\
85The rule does not set the `classtype` Suricata meta option.
86Consider adding `classtype` so Suricata can infer the alert priority for this rule.\
87""",
88 ),
89 )
90
91 return issues