def test_victorops_getinfo(): rule = { 'name': 'Test VictorOps Rule', 'type': 'any', 'victorops_api_key': 'xxxx1', 'victorops_routing_key': 'xxxx2', 'victorops_message_type': 'INFO', 'alert': [] } rules_loader = FileRulesLoader({}) rules_loader.load_modules(rule) alert = VictorOpsAlerter(rule) expected_data = {'type': 'victorops', 'victorops_routing_key': 'xxxx2'} actual_data = alert.get_info() assert expected_data == actual_data
def test_alertmanager_required_error(alertmanager_hosts, expected_data): try: rule = {'name': 'Test Alertmanager Rule', 'type': 'any', 'alert': []} if alertmanager_hosts: rule['alertmanager_hosts'] = alertmanager_hosts rules_loader = FileRulesLoader({}) rules_loader.load_modules(rule) alert = AlertmanagerAlerter(rule) actual_data = alert.get_info() assert expected_data == actual_data except Exception as ea: print('ea %s' % str(ea)) assert expected_data in str(ea)
def test_mattermost_author_icon(): 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_author_icon': 'http://author.icon.url', '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_data = { 'attachments': [ { 'fallback': 'Test Mattermost: aaaaa', 'color': 'danger', 'title': 'Test Mattermost', 'pretext': 'aaaaa', 'fields': [], 'text': 'Test Mattermost Rule\n\n', 'author_icon': 'http://author.icon.url' } ], 'username': '******' } 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_pagerduty_alerter_v2_payload_class_args(): rule = { 'name': 'Test PD Rule', 'type': 'any', 'pagerduty_service_key': 'magicalbadgers', 'pagerduty_client_name': 'ponies inc.', 'pagerduty_api_version': 'v2', 'pagerduty_v2_payload_class': 'somefield', 'pagerduty_v2_payload_class_args': ['@timestamp', 'somefield'], 'pagerduty_v2_payload_component': 'mysql', 'pagerduty_v2_payload_group': 'app-stack', 'pagerduty_v2_payload_severity': 'error', 'pagerduty_v2_payload_source': 'mysql.host.name', 'alert': [] } rules_loader = FileRulesLoader({}) rules_loader.load_modules(rule) alert = PagerDutyAlerter(rule) match = {'@timestamp': '2017-01-01T00:00:00', 'somefield': 'foobarbaz'} with mock.patch('requests.post') as mock_post_request: alert.alert([match]) expected_data = { 'client': 'ponies inc.', 'payload': { 'class': 'somefield', 'component': 'mysql', 'group': 'app-stack', 'severity': 'error', 'source': 'mysql.host.name', 'summary': 'Test PD Rule', 'custom_details': { 'information': 'Test PD Rule\n\n@timestamp: 2017-01-01T00:00:00\nsomefield: foobarbaz\n' }, 'timestamp': '2017-01-01T00:00:00' }, 'event_action': 'trigger', 'dedup_key': '', 'routing_key': 'magicalbadgers', } mock_post_request.assert_called_once_with( 'https://events.pagerduty.com/v2/enqueue', data=mock.ANY, headers={'content-type': 'application/json'}, proxies=None) assert expected_data == json.loads( mock_post_request.call_args_list[0][1]['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': '******' } 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_gitter_getinfo(): rule = { 'name': 'Test Gitter Rule', 'type': 'any', 'gitter_webhook_url': 'https://webhooks.gitter.im/e/xxxxx', 'alert': [] } rules_loader = FileRulesLoader({}) rules_loader.load_modules(rule) alert = GitterAlerter(rule) expected_data = { 'type': 'gitter', 'gitter_webhook_url': 'https://webhooks.gitter.im/e/xxxxx' } actual_data = alert.get_info() assert expected_data == actual_data
def test_alertmanager_ea_exception(): with pytest.raises(EAException) as ea: rule = { 'name': 'Test Alertmanager Rule', 'type': 'any', 'alertmanager_hosts': ['http://*****:*****@timestamp': '2021-01-01T00:00:00', 'somefield': 'foobarbaz'} mock_run = mock.MagicMock(side_effect=RequestException) with mock.patch('requests.post', mock_run), pytest.raises(RequestException): alert.alert([match]) assert 'Error posting to Alertmanager' in str(ea)
def test_slack_title_link(): rule = { 'name': 'Test Rule', 'type': 'any', 'slack_webhook_url': 'http://please.dontgohere.slack', 'slack_username_override': 'elastalert', 'slack_title_link': 'http://slack.title.link', 'alert_subject': 'Cool subject', 'alert': [] } rules_loader = FileRulesLoader({}) rules_loader.load_modules(rule) alert = SlackAlerter(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': '******', 'channel': '', 'icon_emoji': ':ghost:', 'attachments': [ { 'color': 'danger', 'title': rule['alert_subject'], 'text': BasicMatchString(rule, match).__str__(), 'mrkdwn_in': ['text', 'pretext'], 'fields': [], 'title_link': 'http://slack.title.link' } ], 'text': '', 'parse': 'none' } mock_post_request.assert_called_once_with( rule['slack_webhook_url'], data=mock.ANY, headers={'content-type': 'application/json'}, proxies=None, verify=True, timeout=10 ) assert expected_data == json.loads(mock_post_request.call_args_list[0][1]['data'])
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': '******', '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_discord(caplog): caplog.set_level(logging.INFO) rule = { 'name': 'Test Discord Rule', 'type': 'any', 'discord_webhook_url': 'http://xxxxxxx', 'discord_emoji_title': ':warning:', 'discord_embed_color': 0xffffff, 'discord_embed_footer': 'footer', 'discord_embed_icon_url': 'http://xxxx/image.png', 'alert': [], 'alert_subject': 'Test Discord' } rules_loader = FileRulesLoader({}) rules_loader.load_modules(rule) alert = DiscordAlerter(rule) match = {'@timestamp': '2021-01-01T00:00:00', 'somefield': 'foobarbaz'} with mock.patch('requests.post') as mock_post_request: alert.alert([match]) expected_data = { 'content': ':warning: Test Discord :warning:', 'embeds': [{ 'description': 'Test Discord Rule\n\n@timestamp: 2021-01-01T00:00:00\nsomefield: foobarbaz\n', 'color': 0xffffff, 'footer': { 'text': 'footer', 'icon_url': 'http://xxxx/image.png' } }] } mock_post_request.assert_called_once_with( rule['discord_webhook_url'], data=mock.ANY, headers={'Content-Type': 'application/json'}, proxies=None, auth=None) actual_data = json.loads(mock_post_request.call_args_list[0][1]['data']) assert expected_data == actual_data assert ( 'elastalert', logging.INFO, 'Alert sent to the webhook http://xxxxxxx') == caplog.record_tuples[0]
def test_file_rules_loader_get_names_recursive(): conf = {'scan_subdirectories': True, 'rules_folder': 'root'} rules_loader = FileRulesLoader(conf) walk_paths = (('root', ['folder_a', 'folder_b'], ('rule.yaml', )), ('root/folder_a', [], ('a.yaml', 'ab.yaml')), ('root/folder_b', [], ('b.yaml', ))) with mock.patch('os.walk') as mock_walk: mock_walk.return_value = walk_paths paths = rules_loader.get_names(conf) paths = [p.replace(os.path.sep, '/') for p in paths] assert 'root/rule.yaml' in paths assert 'root/folder_a/a.yaml' in paths assert 'root/folder_a/ab.yaml' in paths assert 'root/folder_b/b.yaml' in paths assert len(paths) == 4
def test_file_rules_loader_get_names(): # Check for no subdirectory conf = {'scan_subdirectories': False, 'rules_folder': 'root'} rules_loader = FileRulesLoader(conf) files = ['badfile', 'a.yaml', 'b.yaml'] with mock.patch('os.listdir') as mock_list: with mock.patch('os.path.isfile') as mock_path: mock_path.return_value = True mock_list.return_value = files paths = rules_loader.get_names(conf) paths = [p.replace(os.path.sep, '/') for p in paths] assert 'root/a.yaml' in paths assert 'root/b.yaml' in paths assert len(paths) == 2
def test_google_chat_getinfo(): rule = { 'name': 'Test GoogleChat Rule', 'type': 'any', 'googlechat_webhook_url': 'http://xxxxxxx', 'alert': [] } rules_loader = FileRulesLoader({}) rules_loader.load_modules(rule) alert = GoogleChatAlerter(rule) expected_data = { 'type': 'googlechat', 'googlechat_webhook_url': ['http://xxxxxxx'] } actual_data = alert.get_info() assert expected_data == actual_data
def test_http_getinfo(): rule = { 'name': 'Test HTTP Post Alerter Without Payload', 'type': 'any', 'http_post_url': 'http://test.webhook.url', 'alert': [] } rules_loader = FileRulesLoader({}) rules_loader.load_modules(rule) alert = HTTPPostAlerter(rule) expected_data = { 'type': 'http_post', 'http_post_webhook_url': ['http://test.webhook.url'] } actual_data = alert.get_info() assert expected_data == actual_data
def test_google_chat_ea_exception(): with pytest.raises(EAException) as ea: rule = { 'name': 'Test GoogleChat Rule', 'type': 'any', 'googlechat_webhook_url': 'http://xxxxxxx', 'alert': [] } rules_loader = FileRulesLoader({}) rules_loader.load_modules(rule) alert = GoogleChatAlerter(rule) match = {'@timestamp': '2021-01-01T00:00:00', 'somefield': 'foobarbaz'} mock_run = mock.MagicMock(side_effect=RequestException) with mock.patch('requests.post', mock_run), pytest.raises(RequestException): alert.alert([match]) assert 'Error posting to google chat: ' in str(ea)
def test_thehive_getinfo(hive_host, expect): rule = { 'alert': [], 'alert_text': '', 'alert_text_type': 'alert_text_only', 'description': 'test', 'hive_alert_config': { 'customFields': [{ 'name': 'test', 'type': 'string', 'value': 'test.ip' }], 'follow': True, 'severity': 2, 'source': 'elastalert', 'status': 'New', 'tags': ['test.ip'], 'tlp': 3, 'type': 'external' }, 'hive_connection': { 'hive_apikey': '', 'hive_host': hive_host, 'hive_port': 9000 }, 'hive_observable_data_mapping': [{ 'ip': 'test.ip' }], 'name': 'test-thehive', 'tags': ['a', 'b'], 'type': 'any' } rules_loader = FileRulesLoader({}) rules_loader.load_modules(rule) alert = HiveAlerter(rule) expected_data = expect actual_data = alert.get_info() assert expected_data == actual_data
def test_stomp_getinfo(): rule = { 'name': 'Test Rule', 'type': 'any', 'alert_subject': 'Cool subject', 'stomp_hostname': 'localhost', 'stomp_hostport': '61613', 'stomp_login': '******', 'stomp_password': '******', 'alert': [] } rules_loader = FileRulesLoader({}) rules_loader.load_modules(rule) alert = StompAlerter(rule) expected_data = {'type': 'stomp'} actual_data = alert.get_info() assert expected_data == actual_data
def test_ses_getinfo(): rule = { 'name': 'Test Rule', 'type': 'any', 'alert_subject': 'Cool subject', 'ses_from_addr': '*****@*****.**', 'ses_email': '*****@*****.**', 'ses_aws_access_key_id': 'access key id', 'ses_aws_secret_access_key': 'secret access key', 'alert': [] } rules_loader = FileRulesLoader({}) rules_loader.load_modules(rule) alert = SesAlerter(rule) expected_data = {'type': 'ses', 'recipients': ['*****@*****.**']} actual_data = alert.get_info() assert expected_data == actual_data
def test_ses_required_error(ses_email, ses_from_addr, expected_data): try: rule = {'name': 'Test Telegram Rule', 'type': 'any', 'alert': []} if ses_email: rule['ses_email'] = ses_email if ses_from_addr: rule['ses_from_addr'] = ses_from_addr rules_loader = FileRulesLoader({}) rules_loader.load_modules(rule) alert = SesAlerter(rule) actual_data = alert.get_info() assert expected_data == actual_data except Exception as ea: assert expected_data in str(ea)
def test_twilio_getinfo(): rule = { 'name': 'Test Rule', 'type': 'any', 'alert_subject': 'Cool subject', 'twilio_account_sid': 'xxxxx1', 'twilio_auth_token': 'xxxxx2', 'twilio_to_number': 'xxxxx3', 'twilio_from_number': 'xxxxx4', 'alert': [] } rules_loader = FileRulesLoader({}) rules_loader.load_modules(rule) alert = TwilioAlerter(rule) expected_data = {'type': 'twilio', 'twilio_client_name': 'xxxxx4'} actual_data = alert.get_info() assert expected_data == actual_data
def test_line_notify_ea_exception(): with pytest.raises(EAException) as ea: rule = { 'name': 'Test LineNotify Rule', 'type': 'any', 'linenotify_access_token': 'xxxxx', 'alert': [] } rules_loader = FileRulesLoader({}) rules_loader.load_modules(rule) alert = LineNotifyAlerter(rule) match = {'@timestamp': '2021-01-01T00:00:00', 'somefield': 'foobarbaz'} mock_run = mock.MagicMock(side_effect=RequestException) with mock.patch('requests.post', mock_run), pytest.raises(RequestException): alert.alert([match]) assert 'Error posting to Line Notify: ' in str(ea)
def test_slack_getinfo(): rule = { 'name': 'Test Rule', 'type': 'any', 'slack_webhook_url': 'http://please.dontgohere.slack', 'alert_subject': 'Cool subject', 'alert': [] } rules_loader = FileRulesLoader({}) rules_loader.load_modules(rule) alert = SlackAlerter(rule) expected_data = { 'type': 'slack', 'slack_username_override': 'elastalert' } actual_data = alert.get_info() assert expected_data == actual_data
def test_telegram_ea_exception(): with pytest.raises(EAException) as ea: rule = { 'name': 'Test Telegram Rule', 'type': 'any', 'telegram_bot_token': 'xxxxx1', 'telegram_room_id': 'xxxxx2', 'alert': [] } rules_loader = FileRulesLoader({}) rules_loader.load_modules(rule) alert = TelegramAlerter(rule) match = {'@timestamp': '2021-01-01T00:00:00', 'somefield': 'foobarbaz'} mock_run = mock.MagicMock(side_effect=RequestException) with mock.patch('requests.post', mock_run), pytest.raises(RequestException): alert.alert([match]) assert 'Error posting to Telegram: . Details: ' in str(ea)
def test_http_alerter_post_ea_exception(): with pytest.raises(EAException) as ea: rule = { 'name': 'Test HTTP Post Alerter Without Payload', 'type': 'any', 'http_post2_url': 'http://test.webhook.url', 'http_post2_ca_certs': False, 'alert': [] } rules_loader = FileRulesLoader({}) rules_loader.load_modules(rule) alert = HTTPPost2Alerter(rule) match = {'@timestamp': '2017-01-01T00:00:00', 'somefield': 'foobarbaz'} mock_run = mock.MagicMock(side_effect=RequestException) with mock.patch('requests.post', mock_run), pytest.raises(RequestException): alert.alert([match]) assert 'Error posting HTTP Post 2 alert: ' in str(ea)
def test_ms_teams_getinfo(): rule = { 'name': 'Test Rule', 'type': 'any', 'ms_teams_webhook_url': 'http://test.webhook.url', 'alert_subject': 'Cool subject', 'alert': [] } rules_loader = FileRulesLoader({}) rules_loader.load_modules(rule) alert = MsTeamsAlerter(rule) expected_data = { 'type': 'ms_teams', 'ms_teams_webhook_url': ['http://test.webhook.url'] } actual_data = alert.get_info() assert expected_data == actual_data
def test_discord_getinfo(): rule = { 'name': 'Test Discord Rule' + ('a' * 2069), 'type': 'any', 'discord_webhook_url': 'http://xxxxxxx', 'alert': [], 'alert_subject': 'Test Discord' } rules_loader = FileRulesLoader({}) rules_loader.load_modules(rule) alert = DiscordAlerter(rule) expected_data = { 'type': 'discord', 'discord_webhook_url': 'http://xxxxxxx' } actual_data = alert.get_info() assert expected_data == actual_data
def test_tencentsms_get_info(): rule = { 'name': 'Test tencentsms Template Parm', 'type': 'any', 'alert': ["tencent_sms"], "tencent_sms_secret_id": "secret_id", "tencent_sms_secret_key": "secret_key", "tencent_sms_sdk_appid": "1400006666", "tencent_sms_to_number": ["+8613711112222"], "tencent_sms_template_id": "1123835" } rules_loader = FileRulesLoader({}) rules_loader.load_modules(rule) alert = TencentSMSAlerter(rule) excepted = {'type': 'tencent sms', 'to_number': ["+8613711112222"]} actual = alert.get_info() assert excepted == actual
def test_import_filter(): # Check that if a filter is specified the rules are merged: rules_loader = FileRulesLoader(test_config) import_rule = copy.deepcopy(test_rule) del(import_rule['es_host']) del(import_rule['es_port']) import_rule['import'] = 'importme.ymlt' import_me = { 'es_host': 'imported_host', 'es_port': 12349, 'filter': [{'term': {'ratchet': 'clank'}}], } with mock.patch.object(rules_loader, 'get_yaml') as mock_open: mock_open.side_effect = [import_rule, import_me] rules = rules_loader.load_configuration('blah.yaml', test_config) assert rules['filter'] == [{'term': {'ratchet': 'clank'}}, {'term': {'key': 'value'}}]
def test_pagerduty_getinfo(): rule = { 'name': 'Test PD Rule', 'type': 'any', 'pagerduty_service_key': 'magicalbadgers', 'pagerduty_client_name': 'ponies inc.', 'alert': [] } rules_loader = FileRulesLoader({}) rules_loader.load_modules(rule) alert = PagerDutyAlerter(rule) expected_data = { 'type': 'pagerduty', 'pagerduty_client_name': 'ponies inc.' } actual_data = alert.get_info() assert expected_data == actual_data
def test_dingtalk_getinfo(): rule = { 'name': 'Test DingTalk Rule', 'type': 'any', 'dingtalk_access_token': 'xxxxxxx', 'alert': [], 'alert_subject': 'Test DingTalk' } rules_loader = FileRulesLoader({}) rules_loader.load_modules(rule) alert = DingTalkAlerter(rule) expected_data = { 'type': 'dingtalk', "dingtalk_webhook_url": 'https://oapi.dingtalk.com/robot/send?access_token=xxxxxxx' } actual_data = alert.get_info() assert expected_data == actual_data