Skip to content

Commit

Permalink
Merge pull request #302 from nsano-rururu/add_rocketchat_setting
Browse files Browse the repository at this point in the history
Added Rocket.Chat settings
  • Loading branch information
jertel committed Jun 27, 2021
2 parents d7e53a4 + 1b6dc8c commit d455e55
Show file tree
Hide file tree
Showing 4 changed files with 173 additions and 19 deletions.
12 changes: 9 additions & 3 deletions docs/source/ruletypes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2462,14 +2462,20 @@ Optional:

``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
``rocket_chat_emoji_override``: By default ElastAlert 2 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/ .

``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 Rocket.Chat. Set this option using ``hostname:port`` if you need to use a proxy. only supports https.
``rocket_chat_proxy``: By default ElastAlert 2 will not use a network proxy to send notifications to Rocket.Chat. Set this option using ``hostname:port`` if you need to use a proxy. only supports https.

``rocket_chat_ca_certs``: Set this option to ``True`` if you want to validate the SSL certificate.

``rocket_chat_ignore_ssl_errors``: By default ElastAlert 2 will verify SSL certificate. Set this option to ``False`` if you want to ignore SSL errors.

``rocket_chat_timeout``: You can specify a timeout value, in seconds, for making communicating with Rocket.Chat. The default is 10. If a timeout occurs, the alert will be retried next time ElastAlert 2 cycles.

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

Expand Down Expand Up @@ -2498,7 +2504,7 @@ Example rocket_chat_attach_kibana_discover_url, rocket_chat_kibana_discover_colo
rocket_chat_kibana_discover_color: "#ec4b98"
rocket_chat_kibana_discover_title: "Discover in Kibana"

```rocket_chat_alert_fields``: You can add additional fields to your Rocket.Chat 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`.
``rocket_chat_alert_fields``: You can add additional fields to your Rocket.Chat 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::

Expand Down
13 changes: 12 additions & 1 deletion elastalert/alerters/rocketchat.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ def __init__(self, rule):
self.rocket_chat_attach_kibana_discover_url = self.rule.get('rocket_chat_attach_kibana_discover_url', False)
self.rocket_chat_kibana_discover_color = self.rule.get('rocket_chat_kibana_discover_color', '#ec4b98')
self.rocket_chat_kibana_discover_title = self.rule.get('rocket_chat_kibana_discover_title', 'Discover in Kibana')
self.rocket_chat_ignore_ssl_errors = self.rule.get('rocket_chat_ignore_ssl_errors', False)
self.rocket_chat_timeout = self.rule.get('rocket_chat_timeout', 10)
self.rocket_chat_ca_certs = self.rule.get('rocket_chat_ca_certs')

def format_body(self, body):
return body
Expand Down Expand Up @@ -92,11 +95,19 @@ def alert(self, matches):
for url in self.rocket_chat_webhook_url:
for channel_override in self.rocket_chat_channel_override:
try:
if self.rocket_chat_ca_certs:
verify = self.rocket_chat_ca_certs
else:
verify = not self.rocket_chat_ignore_ssl_errors
if self.rocket_chat_ignore_ssl_errors:
requests.packages.urllib3.disable_warnings()
payload['channel'] = channel_override
response = requests.post(
url, data=json.dumps(payload, cls=DateTimeEncoder),
headers=headers,
proxies=proxies)
verify=verify,
proxies=proxies,
timeout=self.rocket_chat_timeout)
warnings.resetwarnings()
response.raise_for_status()
except RequestException as e:
Expand Down
3 changes: 3 additions & 0 deletions elastalert/schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,9 @@ properties:
rocket_chat_attach_kibana_discover_url {type: boolean}
rocket_chat_kibana_discover_color {type: string}
rocket_chat_kibana_discover_title {type: string}
rocket_chat_ca_certs: {type: boolean}
rocket_chat_ignore_ssl_errors: {type: boolean}
rocket_chat_timeout: {type: integer}

### ServiceNow
servicenow_rest_url: {type: string}
Expand Down
164 changes: 149 additions & 15 deletions tests/alerters/rocketchat_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ def test_rocketchat_uses_custom_title(caplog):
rule['rocket_chat_webhook_url'],
data=mock.ANY,
headers={'content-type': 'application/json'},
proxies=None
proxies=None,
timeout=10,
verify=True
)
assert expected_data == json.loads(mock_post_request.call_args_list[0][1]['data'])
assert ('elastalert', logging.INFO, 'Alert sent to Rocket.Chat') == caplog.record_tuples[0]
Expand Down Expand Up @@ -90,7 +92,9 @@ def test_rocketchat_uses_rule_name_when_custom_title_is_not_provided():
rule['rocket_chat_webhook_url'][0],
data=mock.ANY,
headers={'content-type': 'application/json'},
proxies=None
proxies=None,
timeout=10,
verify=True
)
assert expected_data == json.loads(mock_post_request.call_args_list[0][1]['data'])

Expand Down Expand Up @@ -132,7 +136,9 @@ def test_rocketchat_username_override():
rule['rocket_chat_webhook_url'],
data=mock.ANY,
headers={'content-type': 'application/json'},
proxies=None
proxies=None,
timeout=10,
verify=True
)
assert expected_data == json.loads(mock_post_request.call_args_list[0][1]['data'])

Expand Down Expand Up @@ -173,7 +179,9 @@ def test_rocketchat_chat_channel():
rule['rocket_chat_webhook_url'][0],
data=mock.ANY,
headers={'content-type': 'application/json'},
proxies=None
proxies=None,
timeout=10,
verify=True
)
assert expected_data == json.loads(mock_post_request.call_args_list[0][1]['data'])

Expand Down Expand Up @@ -228,7 +236,9 @@ def test_rocketchat_uses_list_of_custom_rocket_chat_channel():
rule['rocket_chat_webhook_url'][0],
data=mock.ANY,
headers={'content-type': 'application/json'},
proxies=None
proxies=None,
timeout=10,
verify=True
)
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'])
Expand Down Expand Up @@ -270,7 +280,9 @@ def test_rocketchat_emoji_override():
rule['rocket_chat_webhook_url'][0],
data=mock.ANY,
headers={'content-type': 'application/json'},
proxies=None
proxies=None,
timeout=10,
verify=True
)
assert expected_data == json.loads(mock_post_request.call_args_list[0][1]['data'])

Expand Down Expand Up @@ -310,7 +322,9 @@ def test_rocketchat_emoji_override_blank():
rule['rocket_chat_webhook_url'][0],
data=mock.ANY,
headers={'content-type': 'application/json'},
proxies=None
proxies=None,
timeout=10,
verify=True
)
assert expected_data == json.loads(mock_post_request.call_args_list[0][1]['data'])

Expand Down Expand Up @@ -362,7 +376,9 @@ def test_rocketchat_msg_color(msg_color, except_msg_color):
rule['rocket_chat_webhook_url'],
data=mock.ANY,
headers={'content-type': 'application/json'},
proxies=None
proxies=None,
timeout=10,
verify=True
)
assert expected_data == json.loads(mock_post_request.call_args_list[0][1]['data'])

Expand Down Expand Up @@ -405,7 +421,9 @@ def test_rocketchat_text_string():
rule['rocket_chat_webhook_url'],
data=mock.ANY,
headers={'content-type': 'application/json'},
proxies=None
proxies=None,
timeout=10,
verify=True
)
assert expected_data == json.loads(mock_post_request.call_args_list[0][1]['data'])

Expand Down Expand Up @@ -447,7 +465,9 @@ def test_rocketchat_proxy():
rule['rocket_chat_webhook_url'],
data=mock.ANY,
headers={'content-type': 'application/json'},
proxies={'https': rule['rocket_chat_proxy']}
proxies={'https': rule['rocket_chat_proxy']},
timeout=10,
verify=True
)
assert expected_data == json.loads(mock_post_request.call_args_list[0][1]['data'])

Expand Down Expand Up @@ -513,7 +533,9 @@ def test_rocketchat_alert_fields():
rule['rocket_chat_webhook_url'],
data=mock.ANY,
headers={'content-type': 'application/json'},
proxies=None
proxies=None,
timeout=10,
verify=True
)
assert expected_data == json.loads(mock_post_request.call_args_list[0][1]['data'])

Expand Down Expand Up @@ -677,7 +699,9 @@ def test_rocket_chat_attach_kibana_discover_url_when_generated():
rule['rocket_chat_webhook_url'],
data=mock.ANY,
headers={'content-type': 'application/json'},
proxies=None
proxies=None,
timeout=10,
verify=True
)
assert expected_data == json.loads(mock_post_request.call_args_list[0][1]['data'])

Expand Down Expand Up @@ -722,7 +746,9 @@ def test_rocket_chat_attach_kibana_discover_url_when_not_generated():
rule['rocket_chat_webhook_url'],
data=mock.ANY,
headers={'content-type': 'application/json'},
proxies=None
proxies=None,
timeout=10,
verify=True
)
assert expected_data == json.loads(mock_post_request.call_args_list[0][1]['data'])

Expand Down Expand Up @@ -774,7 +800,9 @@ def test_rocket_chat_kibana_discover_title():
rule['rocket_chat_webhook_url'],
data=mock.ANY,
headers={'content-type': 'application/json'},
proxies=None
proxies=None,
timeout=10,
verify=True
)
assert expected_data == json.loads(mock_post_request.call_args_list[0][1]['data'])

Expand Down Expand Up @@ -826,6 +854,112 @@ def test_rocket_chat_kibana_discover_color():
rule['rocket_chat_webhook_url'],
data=mock.ANY,
headers={'content-type': 'application/json'},
proxies=None
proxies=None,
timeout=10,
verify=True
)
assert expected_data == json.loads(mock_post_request.call_args_list[0][1]['data'])


@pytest.mark.parametrize('ca_certs, ignore_ssl_errors, excpet_verify', [
('', '', True),
('', True, False),
('', False, True),
(True, '', True),
(True, True, True),
(True, False, True),
(False, '', True),
(False, True, False),
(False, False, True)
])
def test_rocket_chat_ca_certs(ca_certs, ignore_ssl_errors, excpet_verify):
rule = {
'name': 'Test Rule',
'type': 'any',
'rocket_chat_webhook_url': 'http://please.dontgohere.rocketchat',
'alert_subject': 'Cool subject',
'alert': []
}
if ca_certs:
rule['rocket_chat_ca_certs'] = ca_certs

if ignore_ssl_errors:
rule['rocket_chat_ignore_ssl_errors'] = ignore_ssl_errors

rules_loader = FileRulesLoader({})
rules_loader.load_modules(rule)
alert = RocketChatAlerter(rule)
match = {
'@timestamp': '2017-01-01T00:00:00',
'somefield': 'foobarbaz'
}
with mock.patch('requests.post') as mock_post_request:
alert.alert([match])

expected_data = {
'username': 'elastalert2',
'channel': '',
'emoji': ':ghost:',
'attachments': [
{
'color': 'danger',
'title': 'Cool subject',
'text': BasicMatchString(rule, match).__str__(),
'fields': []
}
],
'text': ''
}
mock_post_request.assert_called_once_with(
rule['rocket_chat_webhook_url'],
data=mock.ANY,
headers={'content-type': 'application/json'},
proxies=None,
verify=excpet_verify,
timeout=10
)
assert expected_data == json.loads(mock_post_request.call_args_list[0][1]['data'])


def test_rocket_chat_uses_custom_timeout():
rule = {
'name': 'Test Rule',
'type': 'any',
'rocket_chat_webhook_url': 'http://please.dontgohere.rocketchat',
'alert_subject': 'Cool subject',
'alert': [],
'rocket_chat_timeout': 20
}
rules_loader = FileRulesLoader({})
rules_loader.load_modules(rule)
alert = RocketChatAlerter(rule)
match = {
'@timestamp': '2016-01-01T00:00:00',
'somefield': 'foobarbaz'
}
with mock.patch('requests.post') as mock_post_request:
alert.alert([match])

expected_data = {
'username': 'elastalert2',
'channel': '',
'emoji': ':ghost:',
'attachments': [
{
'color': 'danger',
'title': 'Cool subject',
'text': BasicMatchString(rule, match).__str__(),
'fields': []
}
],
'text': ''
}
mock_post_request.assert_called_once_with(
rule['rocket_chat_webhook_url'],
data=mock.ANY,
headers={'content-type': 'application/json'},
proxies=None,
verify=True,
timeout=20
)
assert expected_data == json.loads(mock_post_request.call_args_list[0][1]['data'])

0 comments on commit d455e55

Please sign in to comment.