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

Added Rocket.Chat settings #302

Merged
merged 2 commits into from
Jun 27, 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
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'])