2020-06-29 23:19:23 -06:00
|
|
|
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
2021-03-03 22:12:11 -09:00
|
|
|
# or more contributor license agreements. Licensed under the Elastic License
|
|
|
|
|
# 2.0; you may not use this file except in compliance with the Elastic License
|
|
|
|
|
# 2.0.
|
2020-06-29 23:19:23 -06:00
|
|
|
|
|
|
|
|
import copy
|
|
|
|
|
import json
|
|
|
|
|
import unittest
|
2025-07-01 15:20:55 +02:00
|
|
|
from pathlib import Path
|
2020-06-29 23:19:23 -06:00
|
|
|
|
2021-03-24 10:24:32 -06:00
|
|
|
import pytoml
|
|
|
|
|
|
|
|
|
|
from detection_rules.rule_formatter import nested_normalize, toml_write
|
|
|
|
|
from detection_rules.utils import get_etc_path
|
2020-06-29 23:19:23 -06:00
|
|
|
|
2025-07-01 15:20:55 +02:00
|
|
|
tmp_file = "tmp_file.toml"
|
2020-06-29 23:19:23 -06:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class TestRuleTomlFormatter(unittest.TestCase):
|
2021-08-15 06:29:10 +02:00
|
|
|
"""Test that the custom toml formatting is not compromising the integrity of the data."""
|
2025-07-01 15:20:55 +02:00
|
|
|
|
|
|
|
|
maxDiff = None
|
|
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
|
with get_etc_path(["test_toml.json"]).open() as f:
|
|
|
|
|
self.test_data = json.load(f)
|
2020-06-29 23:19:23 -06:00
|
|
|
|
2020-10-01 00:40:55 -05:00
|
|
|
def compare_formatted(self, data, callback=None, kwargs=None):
|
2020-06-29 23:19:23 -06:00
|
|
|
"""Compare formatted vs expected."""
|
2025-07-01 15:20:55 +02:00
|
|
|
tmp_path = Path(tmp_file)
|
2020-06-29 23:19:23 -06:00
|
|
|
try:
|
2025-07-01 15:20:55 +02:00
|
|
|
toml_write(copy.deepcopy(data), tmp_path)
|
2020-06-29 23:19:23 -06:00
|
|
|
|
2025-07-01 15:20:55 +02:00
|
|
|
formatted_data = tmp_path.read_text()
|
|
|
|
|
formatted_contents = pytoml.loads(formatted_data)
|
2020-06-29 23:19:23 -06:00
|
|
|
|
|
|
|
|
# callbacks such as nested normalize leave in line breaks, so this must be manually done
|
2025-07-01 15:20:55 +02:00
|
|
|
query = data.get("rule", {}).get("query")
|
2020-06-29 23:19:23 -06:00
|
|
|
if query:
|
2025-07-01 15:20:55 +02:00
|
|
|
data["rule"]["query"] = query.strip()
|
2020-06-29 23:19:23 -06:00
|
|
|
|
|
|
|
|
original = json.dumps(copy.deepcopy(data), sort_keys=True)
|
|
|
|
|
|
|
|
|
|
if callback:
|
2020-10-01 00:40:55 -05:00
|
|
|
kwargs = kwargs or {}
|
|
|
|
|
formatted_contents = callback(formatted_contents, **kwargs)
|
2020-06-29 23:19:23 -06:00
|
|
|
|
|
|
|
|
# callbacks such as nested normalize leave in line breaks, so this must be manually done
|
2025-07-01 15:20:55 +02:00
|
|
|
query = formatted_contents.get("rule", {}).get("query")
|
2020-06-29 23:19:23 -06:00
|
|
|
if query:
|
2025-07-01 15:20:55 +02:00
|
|
|
formatted_contents["rule"]["query"] = query.strip()
|
2020-06-29 23:19:23 -06:00
|
|
|
|
|
|
|
|
formatted = json.dumps(formatted_contents, sort_keys=True)
|
2025-07-01 15:20:55 +02:00
|
|
|
self.assertEqual(original, formatted, "Formatting may be modifying contents")
|
2020-06-29 23:19:23 -06:00
|
|
|
finally:
|
2025-07-01 15:20:55 +02:00
|
|
|
if tmp_path.exists():
|
|
|
|
|
tmp_path.unlink()
|
2020-06-29 23:19:23 -06:00
|
|
|
|
|
|
|
|
def compare_test_data(self, test_dicts, callback=None):
|
|
|
|
|
"""Compare test data against expected."""
|
|
|
|
|
for data in test_dicts:
|
|
|
|
|
self.compare_formatted(data, callback=callback)
|
|
|
|
|
|
|
|
|
|
def test_normalization(self):
|
|
|
|
|
"""Test that normalization does not change the rule contents."""
|
|
|
|
|
self.compare_test_data([nested_normalize(self.test_data[0])], callback=nested_normalize)
|
|
|
|
|
|
|
|
|
|
def test_formatter_rule(self):
|
|
|
|
|
"""Test that formatter and encoder do not change the rule contents."""
|
|
|
|
|
self.compare_test_data([self.test_data[0]])
|
|
|
|
|
|
|
|
|
|
def test_formatter_deep(self):
|
|
|
|
|
"""Test that the data remains unchanged from formatting."""
|
|
|
|
|
self.compare_test_data(self.test_data[1:])
|