Skip to content

Commit

Permalink
[Bug] [DaC] Metadata maturity field default mismatch and poor enforce…
Browse files Browse the repository at this point in the history
…ment of rule naming conventions (#4285)

* Add stub for solution

* Add date and maturity logic

* Add date and maturity logic

* Version Bump

* Remove Date Inheritance

* Remove Datetime import

(cherry picked from commit 2ea674c)
  • Loading branch information
eric-forte-elastic authored and tradebot-elastic committed Jan 17, 2025
1 parent eb090f6 commit 8eecd39
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 7 deletions.
26 changes: 24 additions & 2 deletions detection_rules/cli_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
DEFAULT_PREBUILT_RULES_DIRS, RuleCollection,
dict_filter)
from .schemas import definitions
from .utils import clear_caches
from .utils import clear_caches, rulename_to_filename


def single_collection(f):
Expand Down Expand Up @@ -95,6 +95,16 @@ def get_collection(*args, **kwargs):
if len(rules) == 0:
client_error("No rules found")

# Warn that if the path does not match the expected path, it will be saved to the expected path
for rule in rules:
threat = rule.contents.data.get("threat")
first_tactic = threat[0].tactic.name if threat else ""
rule_name = rulename_to_filename(rule.contents.data.name, tactic_name=first_tactic)
if rule.path.name != rule_name:
click.secho(
f"WARNING: Rule path does not match required path: {rule.path.name} != {rule_name}", fg="yellow"
)

kwargs["rules"] = rules
return f(*args, **kwargs)

Expand Down Expand Up @@ -200,7 +210,19 @@ def rule_prompt(path=None, rule_type=None, required_only=True, save=True, verbos
# DEFAULT_PREBUILT_RULES_DIRS[0] is a required directory just as a suggestion
suggested_path = Path(DEFAULT_PREBUILT_RULES_DIRS[0]) / contents['name']
path = Path(path or input(f'File path for rule [{suggested_path}]: ') or suggested_path).resolve()
meta = {'creation_date': creation_date, 'updated_date': creation_date, 'maturity': 'development'}
# Inherit maturity from the rule already exists
maturity = "development"
if path.exists():
rules = RuleCollection()
rules.load_file(path)
if rules:
maturity = rules.rules[0].contents.metadata.maturity

meta = {
"creation_date": creation_date,
"updated_date": creation_date,
"maturity": maturity,
}

try:
rule = TOMLRule(path=Path(path), contents=TOMLRuleContents.from_dict({'rule': contents, 'metadata': meta}))
Expand Down
19 changes: 15 additions & 4 deletions detection_rules/kbwrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,10 +237,21 @@ def kibana_export_rules(ctx: click.Context, directory: Path, action_connectors_d
rule_resource["author"] = rule_resource.get("author") or default_author or [rule_resource.get("created_by")]
if isinstance(rule_resource["author"], str):
rule_resource["author"] = [rule_resource["author"]]
contents = TOMLRuleContents.from_rule_resource(rule_resource, maturity="production")
threat = contents.data.get("threat")
first_tactic = threat[0].tactic.name if threat else ""
rule_name = rulename_to_filename(contents.data.name, tactic_name=first_tactic)
# Inherit maturity from the rule already exists
maturity = "development"
threat = rule_resource.get("threat")
first_tactic = threat[0].get("tactic").get("name") if threat else ""
rule_name = rulename_to_filename(rule_resource.get("name"), tactic_name=first_tactic)
# check if directory / f"{rule_name}" exists
if (directory / f"{rule_name}").exists():
rules = RuleCollection()
rules.load_file(directory / f"{rule_name}")
if rules:
maturity = rules.rules[0].contents.metadata.maturity

contents = TOMLRuleContents.from_rule_resource(
rule_resource, maturity=maturity
)
rule = TOMLRule(contents=contents, path=directory / f"{rule_name}")
except Exception as e:
if skip_errors:
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "detection_rules"
version = "0.3.19"
version = "0.4.0"
description = "Detection Rules is the home for rules used by Elastic Security. This repository is used for the development, maintenance, testing, validation, and release of rules for Elastic Security’s Detection Engine."
readme = "README.md"
requires-python = ">=3.12"
Expand Down

0 comments on commit 8eecd39

Please sign in to comment.