Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

List support for mattermost_channel_override #809

Merged
merged 3 commits into from
Apr 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
33 changes: 17 additions & 16 deletions elastalert/alerters/mattermost.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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):
Expand Down
2 changes: 1 addition & 1 deletion elastalert/schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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]}
Expand Down
128 changes: 109 additions & 19 deletions tests/alerters/mattermost_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -249,6 +256,7 @@ def test_mattermost_icon_url_override():
}
],
'username': 'elastalert',
'channel': '',
'icon_url': 'http://xxxx/icon.png'
}

Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -445,7 +455,8 @@ def test_mattermost_footer():
'footer': 'Mattermost footer'
}
],
'username': 'elastalert'
'username': 'elastalert',
'channel': ''
}

mock_post_request.assert_called_once_with(
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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'],
Expand Down Expand Up @@ -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'],
Expand Down Expand Up @@ -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'],
Expand Down Expand Up @@ -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'],
Expand Down Expand Up @@ -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(
Expand All @@ -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'])