Skip to content

Commit 6cb238b

Browse files
frederikb96Mikaayensoneric-forte-elastic
authored
[Enhancement] Add flag to export rules via KQL search on name (#4594)
* Add flag to export rules via KQL search on name * Add KQL to help text Co-authored-by: Eric Forte <[email protected]> * version patch bump * flake8 trimming * pyproject bump * Bump version --------- Co-authored-by: Mika Ayenson, PhD <[email protected]> Co-authored-by: Eric Forte <[email protected]> Co-authored-by: eric-forte-elastic <[email protected]>
1 parent 9b682b7 commit 6cb238b

File tree

5 files changed

+18
-4
lines changed

5 files changed

+18
-4
lines changed

CLI.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,7 @@ Options:
516516
Directory to export exceptions to
517517
-da, --default-author TEXT Default author for rules missing one
518518
-r, --rule-id TEXT Optional Rule IDs to restrict export to
519+
-rn, --rule-name TEXT Optional Rule name to restrict export to (KQL, case-insensitive, supports wildcards)
519520
-ac, --export-action-connectors
520521
Include action connectors in export
521522
-e, --export-exceptions Include exceptions in export

detection_rules/kbwrap.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,8 @@ def _process_imported_items(imported_items_list, item_type_description, item_key
195195
@click.option("--exceptions-directory", "-ed", required=False, type=Path, help="Directory to export exceptions to")
196196
@click.option("--default-author", "-da", type=str, required=False, help="Default author for rules missing one")
197197
@click.option("--rule-id", "-r", multiple=True, help="Optional Rule IDs to restrict export to")
198+
@click.option("--rule-name", "-rn", required=False, help="Optional Rule name to restrict export to "
199+
"(KQL, case-insensitive, supports wildcards)")
198200
@click.option("--export-action-connectors", "-ac", is_flag=True, help="Include action connectors in export")
199201
@click.option("--export-exceptions", "-e", is_flag=True, help="Include exceptions in export")
200202
@click.option("--skip-errors", "-s", is_flag=True, help="Skip errors when exporting rules")
@@ -207,14 +209,24 @@ def _process_imported_items(imported_items_list, item_type_description, item_key
207209
@click.pass_context
208210
def kibana_export_rules(ctx: click.Context, directory: Path, action_connectors_directory: Optional[Path],
209211
exceptions_directory: Optional[Path], default_author: str,
210-
rule_id: Optional[Iterable[str]] = None, export_action_connectors: bool = False,
212+
rule_id: Optional[Iterable[str]] = None, rule_name: Optional[str] = None,
213+
export_action_connectors: bool = False,
211214
export_exceptions: bool = False, skip_errors: bool = False, strip_version: bool = False,
212215
no_tactic_filename: bool = False, local_creation_date: bool = False,
213216
local_updated_date: bool = False) -> List[TOMLRule]:
214217
"""Export custom rules from Kibana."""
215218
kibana = ctx.obj["kibana"]
216219
kibana_include_details = export_exceptions or export_action_connectors
220+
221+
# Only allow one of rule_id or rule_name
222+
if rule_name and rule_id:
223+
raise click.UsageError("Cannot use --rule-id and --rule-name together. Please choose one.")
224+
217225
with kibana:
226+
# Look up rule IDs by name if --rule-name was provided
227+
if rule_name:
228+
found = RuleResource.find(filter=f"alert.attributes.name:{rule_name}")
229+
rule_id = [r["rule_id"] for r in found]
218230
results = RuleResource.export_rules(list(rule_id), exclude_export_details=not kibana_include_details)
219231

220232
# Handle Exceptions Directory Location

lib/kibana/kibana/resources.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ def find(cls, per_page=None, **params) -> iter:
4242
if per_page is None:
4343
per_page = DEFAULT_PAGE_SIZE
4444

45-
params.setdefault("sort_field", "_id")
45+
# _id is no valid sort field so we sort by name by default
46+
params.setdefault("sort_field", "name")
4647
params.setdefault("sort_order", "asc")
4748

4849
return ResourceIterator(cls, cls.BASE_URI + "/_find", per_page=per_page, **params)

lib/kibana/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "detection-rules-kibana"
3-
version = "0.4.2"
3+
version = "0.4.3"
44
description = "Kibana API utilities for Elastic Detection Rules"
55
license = {text = "Elastic License v2"}
66
keywords = ["Elastic", "Kibana", "Detection Rules", "Security", "Elasticsearch"]

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "detection_rules"
3-
version = "1.0.11"
3+
version = "1.0.12"
44
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."
55
readme = "README.md"
66
requires-python = ">=3.12"

0 commit comments

Comments
 (0)