Skip to content

Commit

Permalink
Merge pull request #182 from nsano-rururu/add_rocket_chat
Browse files Browse the repository at this point in the history
Add support for RocketChat
  • Loading branch information
jertel authored May 23, 2021
2 parents d52b3b2 + ccaa9a6 commit 2a053e3
Show file tree
Hide file tree
Showing 6 changed files with 729 additions and 1 deletion.
1 change: 1 addition & 0 deletions docs/source/elastalert.rst
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ Currently, we have support built in for these alert types:
- OpsGenie
- PagerDuty
- PagerTree
- RocketChat
- Squadcast
- ServiceNow
- Slack
Expand Down
40 changes: 40 additions & 0 deletions docs/source/ruletypes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2371,6 +2371,46 @@ Example usage::
- "pagertree"
pagertree_integration_url: "PagerTree Integration URL"

RocketChat
~~~~~~~~~~

RocketChat alerter will send a notification to a predefined channel. The body of the notification is formatted the same as with other alerters.
https://developer.rocket.chat/api/rest-api/methods/chat/postmessage

The alerter requires the following option:

``rocket_chat_webhook_url``: The webhook URL that includes your auth data and the ID of the channel (room) you want to post to. You can use a list of URLs to send to multiple channels.

Optional:

``rocket_chat_username_override``: By default RocketChat will use username defined in Integration when posting to the channel. Use this option to change it (free text).

``rocket_chat_channel_override``: Incoming webhooks have a default channel, but it can be overridden. A public channel can be specified “#other-channel”, and a Direct Message with “@username”.

``rocket_chat_emoji_override``: By default ElastAlert will use the :ghost: emoji when posting to the channel. You can use a different emoji per
ElastAlert rule. Any Apple emoji can be used, see http://emojipedia.org/apple/ . If rocket_chat_icon_url_override parameter is provided, emoji is ignored.

``rocket_chat_msg_color``: By default the alert will be posted with the ‘danger’ color. You can also use ‘good’ or ‘warning’ colors.

``rocket_chat_text_string``: Notification message you want to add.

``rocket_chat_proxy``: By default ElastAlert will not use a network proxy to send notifications to RocketChat. Set this option using ``hostname:port`` if you need to use a proxy.

```rocket_chat_alert_fields``: You can add additional fields to your RocketChat alerts using this field. Specify the title using `title` and a value for the field using `value`. Additionally you can specify whether or not this field should be a `short` field using `short: true`.

Example rocket_chat_alert_fields::

rocket_chat_alert_fields:
- title: Host
value: monitor.host
short: true
- title: Status
value: monitor.status
short: true
- title: Zone
value: beat.name
short: true

Squadcast
~~~~~~~~~

Expand Down
98 changes: 98 additions & 0 deletions elastalert/alerters/rocketchat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# -*- coding: utf-8 -*-
import copy
import json
import requests
from requests.exceptions import RequestException
import warnings

from ..alerts import Alerter, DateTimeEncoder
from ..util import EAException
from ..util import elastalert_logger
from ..util import lookup_es_key


class RocketChatAlerter(Alerter):
""" Creates a RocketChat notification for each alert """
required_options = set(['rocket_chat_webhook_url'])

def __init__(self, rule):
super(RocketChatAlerter, self).__init__(rule)
self.rocket_chat_webhook_url = self.rule['rocket_chat_webhook_url']
if isinstance(self.rocket_chat_webhook_url, str):
self.rocket_chat_webhook_url = [self.rocket_chat_webhook_url]
self.rocket_chat_proxy = self.rule.get('rocket_chat_proxy', None)

self.rocket_chat_username_override = self.rule.get('rocket_chat_username_override', 'elastalert2')
self.rocket_chat_channel_override = self.rule.get('rocket_chat_channel_override', '')
if isinstance(self.rocket_chat_channel_override, str):
self.rocket_chat_channel_override = [self.rocket_chat_channel_override]
self.rocket_chat_emoji_override = self.rule.get('rocket_chat_emoji_override', ':ghost:')
self.rocket_chat_msg_color = self.rule.get('rocket_chat_msg_color', 'danger')
self.rocket_chat_text_string = self.rule.get('rocket_chat_text_string', '')
self.rocket_chat_alert_fields = self.rule.get('rocket_chat_alert_fields', '')

def format_body(self, body):
return body

def get_aggregation_summary_text__maximum_width(self):
width = super(RocketChatAlerter, self).get_aggregation_summary_text__maximum_width()

# Reduced maximum width for prettier Slack display.
return min(width, 75)

def get_aggregation_summary_text(self, matches):
text = super(RocketChatAlerter, self).get_aggregation_summary_text(matches)
if text:
text = '```\n{0}```\n'.format(text)
return text

def populate_fields(self, matches):
alert_fields = []
for arg in self.rocket_chat_alert_fields:
arg = copy.copy(arg)
arg['value'] = lookup_es_key(matches[0], arg['value'])
alert_fields.append(arg)
return alert_fields

def alert(self, matches):
body = self.create_alert_body(matches)
body = self.format_body(body)
headers = {'content-type': 'application/json'}
proxies = {'https': self.rocket_chat_proxy} if self.rocket_chat_proxy else None
payload = {
'username': self.rocket_chat_username_override,
'text': self.rocket_chat_text_string,
'attachments': [
{
'color': self.rocket_chat_msg_color,
'title': self.create_title(matches),
'text': body,
'fields': []
}
]
}

# if we have defined fields, populate noteable fields for the alert
if self.rocket_chat_alert_fields != '':
payload['attachments'][0]['fields'] = self.populate_fields(matches)

if self.rocket_chat_emoji_override != '':
payload['emoji'] = self.rocket_chat_emoji_override

for url in self.rocket_chat_webhook_url:
for channel_override in self.rocket_chat_channel_override:
try:
payload['channel'] = channel_override
response = requests.post(
url, data=json.dumps(payload, cls=DateTimeEncoder),
headers=headers,
proxies=proxies)
warnings.resetwarnings()
response.raise_for_status()
except RequestException as e:
raise EAException("Error posting to Rocket.Chat: %s" % e)
elastalert_logger.info("Alert sent to Rocket.Chat")

def get_info(self):
return {'type': 'rocketchat',
'rocket_chat_username_override': self.rocket_chat_username_override}
5 changes: 4 additions & 1 deletion elastalert/loaders.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
import elastalert.alerters.victorops
import elastalert.alerters.dingtalk
import elastalert.alerters.thehive
import elastalert.alerters.rocketchat

from . import alerts
from . import enhancements
from . import ruletypes
Expand Down Expand Up @@ -114,7 +116,8 @@ class RulesLoader(object):
'dingtalk': elastalert.alerters.dingtalk.DingTalkAlerter,
'chatwork': elastalert.alerters.chatwork.ChatworkAlerter,
'datadog': elastalert.alerters.datadog.DatadogAlerter,
'ses': elastalert.alerters.ses.SesAlerter
'ses': elastalert.alerters.ses.SesAlerter,
'rocketchat': elastalert.alerters.rocketchat.RocketChatAlerter
}

# A partial ordering of alert types. Relative order will be preserved in the resulting alerts list
Expand Down
9 changes: 9 additions & 0 deletions elastalert/schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,15 @@ properties:
pagertree_integration_url: {type: string}
pagertree_proxy: {type: string}

### RocketChat
rocket_chat_webhook_url: *arrayOfString
rocket_chat_username_override: {type: string}
rocket_chat_channel_override: {type: string}
rocket_chat_emoji_override: {type: string}
rocket_chat_msg_color: {enum: [good, warning, danger]}
rocket_chat_text_string: {type: string}
rocket_chat_proxy: {type: string}

### ServiceNow
servicenow_rest_url: {type: string}
username: {type: string}
Expand Down
Loading

0 comments on commit 2a053e3

Please sign in to comment.