From 66b89aa8e9f702d130d7682755f0c04409740c4d Mon Sep 17 00:00:00 2001 From: nsano-rururu Date: Sat, 9 Apr 2022 00:59:53 +0900 Subject: [PATCH 1/2] List support for mattermost_channel_override --- elastalert/alerters/mattermost.py | 33 ++++---- elastalert/schema.yaml | 2 +- tests/alerters/mattermost_test.py | 128 +++++++++++++++++++++++++----- 3 files changed, 127 insertions(+), 36 deletions(-) diff --git a/elastalert/alerters/mattermost.py b/elastalert/alerters/mattermost.py index 0ba6ec81..6cbe7ab3 100644 --- a/elastalert/alerters/mattermost.py +++ b/elastalert/alerters/mattermost.py @@ -25,6 +25,8 @@ def __init__(self, rule): # Override webhook config self.mattermost_username_override = self.rule.get('mattermost_username_override', 'elastalert') self.mattermost_channel_override = self.rule.get('mattermost_channel_override', '') + if isinstance(self.mattermost_channel_override, str): + self.mattermost_channel_override = [self.mattermost_channel_override] self.mattermost_icon_url_override = self.rule.get('mattermost_icon_url_override', '') # Message properties @@ -103,9 +105,6 @@ def alert(self, matches): if self.mattermost_icon_url_override != '': payload['icon_url'] = self.mattermost_icon_url_override - if self.mattermost_channel_override != '': - payload['channel'] = self.mattermost_channel_override - if self.mattermost_title != '': payload['attachments'][0]['title'] = self.mattermost_title @@ -143,19 +142,21 @@ def alert(self, matches): }) for url in self.mattermost_webhook_url: - try: - if self.mattermost_ignore_ssl_errors: - requests.urllib3.disable_warnings() - - response = requests.post( - url, data=json.dumps(payload, cls=DateTimeEncoder), - headers=headers, verify=not self.mattermost_ignore_ssl_errors, - proxies=proxies) - - warnings.resetwarnings() - response.raise_for_status() - except RequestException as e: - raise EAException("Error posting to Mattermost: %s" % e) + for channel_override in self.mattermost_channel_override: + try: + if self.mattermost_ignore_ssl_errors: + requests.urllib3.disable_warnings() + payload['channel'] = channel_override + + response = requests.post( + url, data=json.dumps(payload, cls=DateTimeEncoder), + headers=headers, verify=not self.mattermost_ignore_ssl_errors, + proxies=proxies) + + warnings.resetwarnings() + response.raise_for_status() + except RequestException as e: + raise EAException("Error posting to Mattermost: %s" % e) elastalert_logger.info("Alert sent to Mattermost") def get_info(self): diff --git a/elastalert/schema.yaml b/elastalert/schema.yaml index 6a416456..6b116dd4 100644 --- a/elastalert/schema.yaml +++ b/elastalert/schema.yaml @@ -504,7 +504,7 @@ properties: mattermost_proxy: {type: string} mattermost_ignore_ssl_errors: {type: boolean} mattermost_username_override: {type: string} - mattermost_channel_override: {type: string} + mattermost_channel_override: *arrayOfString mattermost_icon_url_override: {type: string} mattermost_msg_pretext: {type: string} mattermost_msg_color: {enum: [good, warning, danger]} diff --git a/tests/alerters/mattermost_test.py b/tests/alerters/mattermost_test.py index 92cdf3cb..58a66296 100644 --- a/tests/alerters/mattermost_test.py +++ b/tests/alerters/mattermost_test.py @@ -44,7 +44,9 @@ def test_mattermost_proxy(caplog): 'fields': [], 'text': 'Test Mattermost Rule\n\n' } - ], 'username': 'elastalert' + ], + 'username': 'elastalert', + 'channel': '', } mock_post_request.assert_called_once_with( @@ -91,7 +93,9 @@ def test_mattermost_alert_text_only(): 'fields': [], 'text': 'Test Mattermost Rule\n\n' } - ], 'username': 'elastalert' + ], + 'username': 'elastalert', + 'channel': '', } mock_post_request.assert_called_once_with( @@ -138,7 +142,8 @@ def test_mattermost_not_alert_text_only(): } ], 'text': 'Test Mattermost Rule\n\n', - 'username': 'elastalert' + 'username': 'elastalert', + 'channel': '' } mock_post_request.assert_called_once_with( @@ -200,7 +205,9 @@ def test_mattermost_msg_fields(): ], 'text': 'Test Mattermost Rule\n\n' } - ], 'username': 'elastalert' + ], + 'username': 'elastalert', + 'channel': '' } mock_post_request.assert_called_once_with( @@ -249,6 +256,7 @@ def test_mattermost_icon_url_override(): } ], 'username': 'elastalert', + 'channel': '', 'icon_url': 'http://xxxx/icon.png' } @@ -346,7 +354,8 @@ def test_mattermost_ignore_ssl_errors(): 'text': 'Test Mattermost Rule\n\n' } ], - 'username': 'elastalert' + 'username': 'elastalert', + 'channel': '' } mock_post_request.assert_called_once_with( @@ -396,7 +405,8 @@ def test_mattermost_title_link(): 'title_link': 'http://title.url' } ], - 'username': 'elastalert' + 'username': 'elastalert', + 'channel': '' } mock_post_request.assert_called_once_with( @@ -445,7 +455,8 @@ def test_mattermost_footer(): 'footer': 'Mattermost footer' } ], - 'username': 'elastalert' + 'username': 'elastalert', + 'channel': '' } mock_post_request.assert_called_once_with( @@ -494,7 +505,8 @@ def test_mattermost_footer_icon(): 'footer_icon': 'http://icon.url' } ], - 'username': 'elastalert' + 'username': 'elastalert', + 'channel': '' } mock_post_request.assert_called_once_with( @@ -543,7 +555,8 @@ def test_mattermost_image_url(): 'image_url': 'http://image.url' } ], - 'username': 'elastalert' + 'username': 'elastalert', + 'channel': '' } mock_post_request.assert_called_once_with( @@ -592,7 +605,8 @@ def test_mattermost_thumb_url(): 'thumb_url': 'http://thumb.url' } ], - 'username': 'elastalert' + 'username': 'elastalert', + 'channel': '' } mock_post_request.assert_called_once_with( @@ -641,7 +655,8 @@ def test_mattermost_author_name(): 'author_name': 'author name' } ], - 'username': 'elastalert' + 'username': 'elastalert', + 'channel': '' } mock_post_request.assert_called_once_with( @@ -690,7 +705,8 @@ def test_mattermost_author_link(): 'author_link': 'http://author.link.url' } ], - 'username': 'elastalert' + 'username': 'elastalert', + 'channel': '' } mock_post_request.assert_called_once_with( @@ -739,7 +755,8 @@ def test_mattermost_author_icon(): 'author_icon': 'http://author.icon.url' } ], - 'username': 'elastalert' + 'username': 'elastalert', + 'channel': '' } mock_post_request.assert_called_once_with( @@ -841,7 +858,8 @@ def test_mattermost_msg_color(msg_color, except_msg_color): 'author_icon': 'http://author.icon.url' } ], - 'username': 'elastalert' + 'username': 'elastalert', + 'channel': '' } mock_post_request.assert_called_once_with( @@ -944,7 +962,9 @@ def test_mattermost_attach_kibana_discover_url_when_generated(): 'title': 'Discover in Kibana', 'title_link': 'http://localhost:5601/app/discover#/' } - ], 'username': 'elastalert' + ], + 'username': 'elastalert', + 'channel': '' } mock_post_request.assert_called_once_with( rule['mattermost_webhook_url'], @@ -986,7 +1006,9 @@ def test_mattermost_attach_kibana_discover_url_when_not_generated(): 'fields': [], 'text': 'Test Rule\n\n' } - ], 'username': 'elastalert' + ], + 'username': 'elastalert', + 'channel': '' } mock_post_request.assert_called_once_with( rule['mattermost_webhook_url'], @@ -1035,7 +1057,9 @@ def test_mattermost_kibana_discover_title(): 'title': 'Click to discover in Kibana', 'title_link': 'http://localhost:5601/app/discover#/' } - ], 'username': 'elastalert' + ], + 'username': 'elastalert', + 'channel': '' } mock_post_request.assert_called_once_with( rule['mattermost_webhook_url'], @@ -1084,7 +1108,9 @@ def test_mattermost_kibana_discover_color(): 'title': 'Discover in Kibana', 'title_link': 'http://localhost:5601/app/discover#/' } - ], 'username': 'elastalert' + ], + 'username': 'elastalert', + 'channel': '' } mock_post_request.assert_called_once_with( rule['mattermost_webhook_url'], @@ -1130,7 +1156,9 @@ def test_mattermost_username_override(): 'fields': [], 'text': 'Test Mattermost Rule\n\n' } - ], 'username': 'test user' + ], + 'username': 'test user', + 'channel': '' } mock_post_request.assert_called_once_with( @@ -1143,3 +1171,65 @@ def test_mattermost_username_override(): actual_data = json.loads(mock_post_request.call_args_list[0][1]['data']) assert expected_data == actual_data + + +def test_mattermost_uses_list_of_custom_mattermost_channel(): + rule = { + 'name': 'Test Mattermost Rule', + 'type': 'any', + 'alert_text_type': 'alert_text_only', + 'mattermost_webhook_url': 'http://xxxxx', + 'mattermost_msg_pretext': 'aaaaa', + 'mattermost_msg_color': 'danger', + 'mattermost_channel_override': ['#test-alert', '#test-alert2'], + 'alert': [], + 'alert_subject': 'Test Mattermost' + } + rules_loader = FileRulesLoader({}) + rules_loader.load_modules(rule) + alert = MattermostAlerter(rule) + match = { + '@timestamp': '2021-01-01T00:00:00', + 'somefield': 'foobarbaz' + } + with mock.patch('requests.post') as mock_post_request: + alert.alert([match]) + + expected_data1 = { + 'attachments': [ + { + 'fallback': 'Test Mattermost: aaaaa', + 'color': 'danger', + 'title': 'Test Mattermost', + 'pretext': 'aaaaa', + 'fields': [], + 'text': 'Test Mattermost Rule\n\n' + } + ], + 'username': 'elastalert', + 'channel': '#test-alert' + } + expected_data2 = { + 'attachments': [ + { + 'fallback': 'Test Mattermost: aaaaa', + 'color': 'danger', + 'title': 'Test Mattermost', + 'pretext': 'aaaaa', + 'fields': [], + 'text': 'Test Mattermost Rule\n\n' + } + ], + 'username': 'elastalert', + 'channel': '#test-alert2' + } + mock_post_request.assert_called_with( + rule['mattermost_webhook_url'], + data=mock.ANY, + headers={'content-type': 'application/json'}, + verify=True, + proxies=None + ) + + assert expected_data1 == json.loads(mock_post_request.call_args_list[0][1]['data']) + assert expected_data2 == json.loads(mock_post_request.call_args_list[1][1]['data']) From 0973ec0686f50bc37581ea606c9974bd35f55b29 Mon Sep 17 00:00:00 2001 From: nsano-rururu Date: Sat, 9 Apr 2022 01:05:44 +0900 Subject: [PATCH 2/2] Update ChangeLog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a7e8a051..f5a3f8a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ - Add support for Kibana 8.1 for Kibana Discover - [#763](https://github.com/jertel/elastalert2/pull/763) - @nsano-rururu - [MS Teams] Add arbitrary text value support for Facts - [#790](https://github.com/jertel/elastalert2/pull/790) - @iamxeph - [MS Teams] Use alert_subject as ms_teams_alert_summary if ms_teams_alert_summary is not set - [#802](https://github.com/jertel/elastalert2/pull/802) - @iamxeph +- [Mattermost] List support for mattermost_channel_override - [#809](https://github.com/jertel/elastalert2/pull/809) - @nsano-rururu ## Other changes - [Docs] Update FAQ ssl_show_warn - [#764](https://github.com/jertel/elastalert2/pull/764) - @nsano-rururu