diff --git a/elastalert/alerters/iris.py b/elastalert/alerters/iris.py index 1f20ae5b..c86256de 100644 --- a/elastalert/alerters/iris.py +++ b/elastalert/alerters/iris.py @@ -34,13 +34,28 @@ def __init__(self, rule): self.alert_context = self.rule.get('iris_alert_context', None) self.iocs = self.rule.get('iris_iocs', None) + def lookup_field(self, match: dict, field_name: str, default): + """Populates a field with values depending on the contents of the Elastalert match + provided to it. + + Uses a similar algorithm to that implemented to populate the `alert_text_args`. + First checks any fields found in the match provided, then any fields defined in + the rule, finally returning the default value provided if no value can be found. + """ + field_value = lookup_es_key(match, field_name) + if field_value is None: + field_value = self.rule.get(field_name, default) + + return field_value + def make_alert_context_records(self, matches): alert_context = {} for key, value in self.alert_context.items(): + data = str(self.lookup_field(matches[0], value, '')) alert_context.update( { - key: matches[0].get(value) + key: data } ) diff --git a/tests/alerters/iris_test.py b/tests/alerters/iris_test.py index 85fd2265..2ad0bfce 100644 --- a/tests/alerters/iris_test.py +++ b/tests/alerters/iris_test.py @@ -215,6 +215,86 @@ def test_iris_make_alert_maximal(caplog): assert expected_data == actual_data +def test_iris_make_alert_maximal_with_nested_json(caplog): + caplog.set_level(logging.INFO) + rule = { + 'name': 'Test Maximal Alert Body', + 'type': 'any', + 'iris_host': '127.0.0.1', + 'iris_api_token': 'token 12345', + 'iris_customer_id': 1, + 'iris_description': 'test description in alert', + 'iris_alert_note': 'test note', + 'iris_alert_tags': 'test, alert', + 'iris_overwrite_timestamp': True, + 'iris_alert_source_link': 'https://example.com', + 'iris_iocs': [ + { + 'ioc_description': 'source address', + 'ioc_tags': 'ip, ipv4', + 'ioc_tlp_id': 1, + 'ioc_type_id': 76, + 'ioc_value': 'host.src_ip' + }, + { + 'ioc_description': 'target username', + 'ioc_tags': 'login, username', + 'ioc_tlp_id': 3, + 'ioc_type_id': 3, + 'ioc_value': 'username' + } + ], + 'iris_alert_context': {'username': 'username', 'ip': 'host.src_ip', 'login_status': 'event_status'}, + 'alert': [], + } + + rules_loader = FileRulesLoader({}) + rules_loader.load_modules(rule) + alert = IrisAlerter(rule) + + match = { + '@timestamp': '2023-10-21 20:00:00.000', 'username': 'evil_user', 'host': {'src_ip': '172.20.1.1'}, 'dst_ip': '10.0.0.1', + 'event_type': 'login', 'event_status': 'success' + } + + expected_data = { + "alert_title": 'Test Maximal Alert Body', + "alert_description": 'test description in alert', + "alert_source": "ElastAlert2", + "alert_severity_id": 1, + "alert_status_id": 2, + "alert_source_event_time": '2023-10-21 20:00:00.000', + "alert_note": 'test note', + "alert_tags": 'test, alert', + "alert_customer_id": 1, + "alert_source_link": 'https://example.com', + "alert_iocs": [ + { + 'ioc_description': 'source address', + 'ioc_tags': 'ip, ipv4', + 'ioc_tlp_id': 1, + 'ioc_type_id': 76, + 'ioc_value': '172.20.1.1' + }, + { + 'ioc_description': 'target username', + 'ioc_tags': 'login, username', + 'ioc_tlp_id': 3, + 'ioc_type_id': 3, + 'ioc_value': 'evil_user' + } + ], + "alert_context": { + 'username': 'evil_user', + 'ip': '172.20.1.1', + 'login_status': 'success' + }, + } + + actual_data = alert.make_alert([match]) + assert expected_data == actual_data + + def test_iris_make_case_minimal(caplog): caplog.set_level(logging.INFO) rule = {