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

Mattermost add kibana discover and bugfix #239

Merged
merged 6 commits into from
Jun 6, 2021
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
6 changes: 4 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
- Add support for Elasticsearch API key authentication - [#208](https://github.com/jertel/elastalert2/pull/208) - @vbisserie
- Add support for Elasticsearch 7.13 for building Kibana Discover URLs - [#212](https://github.com/jertel/elastalert2/pull/212) - @nsano-rururu
- Follow symbolic links when traversing rules folder for rule files - [#214](https://github.com/jertel/elastalert2/pull/214) - @vbisserie
- Support optional suppression of SSL log warnings when http-posting alerts - [#222](https://github.com/jertel/elastalert2/pull/222/files) - @nsano-rururu
- Support optional suppression of SSL log warnings when http-posting alerts - [#222](https://github.com/jertel/elastalert2/pull/222) - @nsano-rururu
- Add support for inclusion of Kibana Discover URLs in MatterMost messages - [#239](https://github.com/jertel/elastalert2/pull/239) - @nsano-rururu

## Other changes
- Speed up unit tests by adding default parallelism - [#164](https://github.com/jertel/elastalert2/pull/164) - @ferozsalam
Expand All @@ -46,7 +47,8 @@
- Migrate away from external test mock dependency - [#233](https://github.com/jertel/elastalert2/pull/233) - @nsano-rururu
- Improve ElastAlert 2 documentation relating to running scenarios - [#234](https://github.com/jertel/elastalert2/pull/234) - @ferozsalam
- Improve test coverage and correct dict lookup syntax for alerter init functions - [#235](https://github.com/jertel/elastalert2/pull/235) - @nsano-rururu

- Fix schema bug with MatterMost alerts - [#239](https://github.com/jertel/elastalert2/pull/239) - @nsano-rururu
-
# 2.1.0

## Breaking changes
Expand Down
6 changes: 6 additions & 0 deletions docs/source/ruletypes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2223,6 +2223,12 @@ Example mattermost_msg_fields::

``mattermost_author_icon``: An optional URL used to display a 16x16 pixel icon beside the author_name. Defaults to "".

``mattermost_attach_kibana_discover_url``: Enables the attachment of the ``kibana_discover_url`` to the mattermost notification. The config ``generate_kibana_discover_url`` must also be ``True`` in order to generate the url. Defaults to ``False``.

``mattermost_kibana_discover_color``: The color of the Kibana Discover url attachment. Defaults to ``#ec4b98``.

``mattermost_kibana_discover_title``: The title of the Kibana Discover url attachment. Defaults to ``Discover in Kibana``.

Microsoft Teams
~~~~~~~~~~~~~~~

Expand Down
12 changes: 12 additions & 0 deletions elastalert/alerters/mattermost.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ def __init__(self, rule):
self.mattermost_author_name = self.rule.get('mattermost_author_name', '')
self.mattermost_author_link = self.rule.get('mattermost_author_link', '')
self.mattermost_author_icon = self.rule.get('mattermost_author_icon', '')
self.mattermost_attach_kibana_discover_url = self.rule.get('mattermost_attach_kibana_discover_url', False)
self.mattermost_kibana_discover_color = self.rule.get('mattermost_kibana_discover_color', '#ec4b98')
self.mattermost_kibana_discover_title = self.rule.get('mattermost_kibana_discover_title', 'Discover in Kibana')

def get_aggregation_summary_text__maximum_width(self):
width = super(MattermostAlerter, self).get_aggregation_summary_text__maximum_width()
Expand Down Expand Up @@ -128,6 +131,15 @@ def alert(self, matches):
if self.mattermost_author_icon != '':
payload['attachments'][0]['author_icon'] = self.mattermost_author_icon

if self.mattermost_attach_kibana_discover_url:
kibana_discover_url = lookup_es_key(matches[0], 'kibana_discover_url')
if kibana_discover_url:
payload['attachments'].append({
'color': self.mattermost_kibana_discover_color,
'title': self.mattermost_kibana_discover_title,
'title_link': kibana_discover_url
})

for url in self.mattermost_webhook_url:
try:
if self.mattermost_ignore_ssl_errors:
Expand Down
13 changes: 10 additions & 3 deletions elastalert/schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ definitions:
milliseconds: {type: number}
schedule: {type: string}

filter: &filter {}

mattermostField: &mattermostField
type: object
additionalProperties: false
Expand All @@ -45,6 +43,12 @@ definitions:
args: *arrayOfString
short: {type: boolean}

arrayOfMattermostFields: &arrayOfMattermostField
type: array
items: *mattermostField

filter: &filter {}

required: [type, index, alert]
type: object

Expand Down Expand Up @@ -397,7 +401,7 @@ properties:
mattermost_icon_url_override: {type: string}
mattermost_msg_pretext: {type: string}
mattermost_msg_color: {enum: [good, warning, danger]}
mattermost_msg_fields: *mattermostField
mattermost_msg_fields: *arrayOfMattermostField
mattermost_title_link: {type: string}
mattermost_footer: {type: string}
mattermost_footer_icon: {type: string}
Expand All @@ -406,6 +410,9 @@ properties:
mattermost_author_name: {type: string}
mattermost_author_link: {type: string}
mattermost_author_icon: {type: string}
mattermost_attach_kibana_discover_url {type: boolean}
mattermost_kibana_discover_color {type: string}
mattermost_kibana_discover_title {type: string}

### Microsoft Teams
ms_teams_webhook_url: *arrayOfString
Expand Down
188 changes: 188 additions & 0 deletions tests/alerters/mattermost_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -904,3 +904,191 @@ def test_mattermost_required_error(mattermost_webhook_url, expected_data):
assert expected_data == actual_data
except Exception as ea:
assert expected_data in str(ea)


def test_mattermost_attach_kibana_discover_url_when_generated():
rule = {
'name': 'Test Rule',
'type': 'any',
'alert_text_type': 'alert_text_only',
'mattermost_attach_kibana_discover_url': True,
'mattermost_webhook_url': 'http://please.dontgohere.mattermost',
'alert': []
}
rules_loader = FileRulesLoader({})
rules_loader.load_modules(rule)
alert = MattermostAlerter(rule)
match = {
'@timestamp': '2021-01-01T00:00:00',
'kibana_discover_url': 'http://localhost:5601/app/discover#/'
}
with mock.patch('requests.post') as mock_post_request:
alert.alert([match])

expected_data = {
'attachments': [
{
'fallback': 'Test Rule: ',
'color': 'danger',
'title': 'Test Rule',
'pretext': '',
'fields': [],
'text': 'Test Rule\n\n'
},
{
'color': '#ec4b98',
'title': 'Discover in Kibana',
'title_link': 'http://localhost:5601/app/discover#/'
}
], 'username': 'elastalert'
}
mock_post_request.assert_called_once_with(
rule['mattermost_webhook_url'],
data=mock.ANY,
headers={'content-type': 'application/json'},
verify=True,
proxies=None
)

actual_data = json.loads(mock_post_request.call_args_list[0][1]['data'])
assert expected_data == actual_data


def test_mattermost_attach_kibana_discover_url_when_not_generated():
rule = {
'name': 'Test Rule',
'type': 'any',
'alert_text_type': 'alert_text_only',
'mattermost_attach_kibana_discover_url': True,
'mattermost_webhook_url': 'http://please.dontgohere.mattermost',
'alert': []
}
rules_loader = FileRulesLoader({})
rules_loader.load_modules(rule)
alert = MattermostAlerter(rule)
match = {
'@timestamp': '2021-01-01T00:00:00'
}
with mock.patch('requests.post') as mock_post_request:
alert.alert([match])

expected_data = {
'attachments': [
{
'fallback': 'Test Rule: ',
'color': 'danger',
'title': 'Test Rule',
'pretext': '',
'fields': [],
'text': 'Test Rule\n\n'
}
], 'username': 'elastalert'
}
mock_post_request.assert_called_once_with(
rule['mattermost_webhook_url'],
data=mock.ANY,
headers={'content-type': 'application/json'},
verify=True,
proxies=None
)

actual_data = json.loads(mock_post_request.call_args_list[0][1]['data'])
assert expected_data == actual_data


def test_mattermost_kibana_discover_title():
rule = {
'name': 'Test Rule',
'type': 'any',
'alert_text_type': 'alert_text_only',
'mattermost_attach_kibana_discover_url': True,
'mattermost_kibana_discover_title': 'Click to discover in Kibana',
'mattermost_webhook_url': 'http://please.dontgohere.mattermost',
'alert': []
}
rules_loader = FileRulesLoader({})
rules_loader.load_modules(rule)
alert = MattermostAlerter(rule)
match = {
'@timestamp': '2021-01-01T00:00:00',
'kibana_discover_url': 'http://localhost:5601/app/discover#/'
}
with mock.patch('requests.post') as mock_post_request:
alert.alert([match])

expected_data = {
'attachments': [
{
'fallback': 'Test Rule: ',
'color': 'danger',
'title': 'Test Rule',
'pretext': '',
'fields': [],
'text': 'Test Rule\n\n'
},
{
'color': '#ec4b98',
'title': 'Click to discover in Kibana',
'title_link': 'http://localhost:5601/app/discover#/'
}
], 'username': 'elastalert'
}
mock_post_request.assert_called_once_with(
rule['mattermost_webhook_url'],
data=mock.ANY,
headers={'content-type': 'application/json'},
verify=True,
proxies=None
)

actual_data = json.loads(mock_post_request.call_args_list[0][1]['data'])
assert expected_data == actual_data


def test_mattermost_kibana_discover_color():
rule = {
'name': 'Test Rule',
'type': 'any',
'alert_text_type': 'alert_text_only',
'mattermost_attach_kibana_discover_url': True,
'mattermost_kibana_discover_color': 'blue',
'mattermost_webhook_url': 'http://please.dontgohere.mattermost',
'alert': []
}
rules_loader = FileRulesLoader({})
rules_loader.load_modules(rule)
alert = MattermostAlerter(rule)
match = {
'@timestamp': '2021-01-01T00:00:00',
'kibana_discover_url': 'http://localhost:5601/app/discover#/'
}
with mock.patch('requests.post') as mock_post_request:
alert.alert([match])

expected_data = {
'attachments': [
{
'fallback': 'Test Rule: ',
'color': 'danger',
'title': 'Test Rule',
'pretext': '',
'fields': [],
'text': 'Test Rule\n\n'
},
{
'color': 'blue',
'title': 'Discover in Kibana',
'title_link': 'http://localhost:5601/app/discover#/'
}
], 'username': 'elastalert'
}
mock_post_request.assert_called_once_with(
rule['mattermost_webhook_url'],
data=mock.ANY,
headers={'content-type': 'application/json'},
verify=True,
proxies=None
)

actual_data = json.loads(mock_post_request.call_args_list[0][1]['data'])
assert expected_data == actual_data