Beispiel #1
0
def test_http_post_post_data_nested_dict():
    # Posting - nested post data structures (new style)
    alert = None
    rule = {
        'type': mock_rule(),
        'name': 'Test HTTP Post Rule',
        'http_post_url' : 'http://www.example.com/endpoint',
        'http_post_headers' : {
            'name1':'value1'
        },
        'http_post_data' : {
            '@timestamp' : '{@timestamp}',
            'data': {
                'somefield1' : '{somefield}',
                'nestedfield' : '{nested[field]}'
            }
        },
        'new_style_string_format': True
    }
    match = {'@timestamp': '2014-01-01T00:00:00',
         'somefield': 'foobarbaz',
         'nested': {'field': 1}}
    alert = HttpPostAlerter(rule)

    expected_data = '{"@timestamp": "2014-01-01T00:00:00", "data": {"nestedfield": "1", "somefield1": "foobarbaz"}}'
    expected_headers = {'Content-Type': 'application/json', 'Accept': 'application/json;charset=utf-8', 'name1': 'value1'}
    with mock.patch("elastalert_modules.cx_alerters.requests.post") as mock_request:
        alert.alert([match])
    mock_request.assert_called_with('http://www.example.com/endpoint', data=expected_data, headers=expected_headers)
Beispiel #2
0
def test_msend_service_slotsetvalues_mc_notes():
    rule = {
        'type': mock_rule(),
        'new_style_string_format': True,
        'alert_subject': 'Alert Subject',
        'alert_text': 'Alert Text',
        'msend_service_url' : 'http://www.example.com/',
        'msend_cell_name': 'somecellname',
        'msend_event_class': 'EVENT',
        'msend_event_severity': 'WARNING',
        'msend_slotsetvalues' : {
            'mc_host': 'testhost',
            'mc_tool': 'Elasticsearch',
            'mc_long_msg': '{match[somefield]}',
            'mc_more_msg': '{match[nested][field]}',
            'mc_notes': ['{match[@timestamp]}', 'ElasticSearch', 'notes #1', '{match[@timestamp]}', 'ElasticSearch','notes #2', '{match[@timestamp]}', 'ElasticSearch','more notes']
        }
    }
    match = {'@timestamp': '2014-01-01T00:00:00',
         'somefield': 'foobarbaz',
         'nested': {'field': 1}}
    alert = MSendServiceAlerter(rule)
    expected_headers = {'Content-Type': 'application/json', 'Accept': 'application/json;charset=utf-8'}
    expected_data = '{"msend_event_severity": "WARNING", "msend_event_slotvalues": {"mc_long_msg": "foobarbaz", "mc_more_msg": "1", "mc_notes": "[\'0x52c35a80\',\'ElasticSearch\',\'notes #1\',\'0x52c35a80\',\'ElasticSearch\',\'notes #2\',\'0x52c35a80\',\'ElasticSearch\',\'more notes\']", "mc_host": "testhost", "mc_tool": "Elasticsearch"}, "msend_cell_name": "somecellname", "msend_event_message": "Alert Subject", "msend_event_class": "EVENT"}'
    with mock.patch("elastalert_modules.cx_alerters.requests.post") as mock_post:
        alert.alert([match])
    mock_post.assert_called_with('http://www.example.com/', headers = expected_headers, data = expected_data)
Beispiel #3
0
def test_http_post_old_style_post_data():
    # Posting - Data formatting (old style)
    alert = None
    rule = {
        'type': mock_rule(),
        'name': 'Test HTTP Post Rule',
        'http_post_url' : 'http://www.example.com/endpoint',
        'http_post_headers' : {
            'name1':'value1'
        },
        'http_post_data' : {
            '@timestamp' : '%(@timestamp)s',
            'somefield1' : '%(somefield)s'
        },
        'new_style_string_format': False
    }
    match = {'@timestamp': '2014-01-01T00:00:00',
         'somefield': 'foobarbaz',
         'nested': {'field': 1}}
    alert = HttpPostAlerter(rule)

    expected_data = '{"@timestamp": "2014-01-01T00:00:00", "somefield1": "foobarbaz"}'
    expected_headers = {'Content-Type': 'application/json', 'Accept': 'application/json;charset=utf-8', 'name1': 'value1'}
    with mock.patch("elastalert_modules.cx_alerters.requests.post") as mock_request:
        alert.alert([match])
    mock_request.assert_called_with('http://www.example.com/endpoint', data=expected_data, headers=expected_headers)
Beispiel #4
0
def test_opsgenie_details_with_constant_value_matchs():
    rule = {
        'name': 'Opsgenie Details',
        'type': mock_rule(),
        'opsgenie_account': 'genies',
        'opsgenie_key': 'ogkey',
        'opsgenie_details': {
            'Foo': 'Bar'
        }
    }
    match = {'@timestamp': '2014-10-31T00:00:00'}
    alert = OpsGenieAlerter(rule)

    with mock.patch('requests.post') as mock_post_request:
        alert.alert([match, match])

    mock_post_request.assert_called_once_with(
        'https://api.opsgenie.com/v2/alerts',
        headers={
            'Content-Type': 'application/json',
            'Authorization': 'GenieKey ogkey'
        },
        json=mock.ANY,
        proxies=None)

    expected_json = {
        'description':
        'Opsgenie Details\n'
        '\n'
        "{'@timestamp': '2014-10-31T00:00:00'}\n"
        '\n'
        '@timestamp: 2014-10-31T00:00:00\n'
        '\n'
        '----------------------------------------\n'
        'Opsgenie Details\n'
        '\n'
        "{'@timestamp': '2014-10-31T00:00:00'}\n"
        '\n'
        '@timestamp: 2014-10-31T00:00:00\n'
        '\n'
        '----------------------------------------\n',
        'details': {
            'Foo': 'Bar'
        },
        'message':
        'ElastAlert: Opsgenie Details',
        'priority':
        None,
        'source':
        'ElastAlert',
        'tags': ['ElastAlert', 'Opsgenie Details'],
        'user':
        '******'
    }
    actual_json = mock_post_request.call_args_list[0][1]['json']
    assert expected_json == actual_json
Beispiel #5
0
def test_opsgenie_parse_responders(caplog):
    caplog.set_level(logging.WARNING)
    rule = {
        'name': 'testOGalert',
        'opsgenie_key': 'ogkey',
        'opsgenie_account': 'genies',
        'opsgenie_addr': 'https://api.opsgenie.com/v2/alerts',
        'opsgenie_recipients': ['{RECEIPIENT_PREFIX}'],
        'opsgenie_recipients_args': {'RECEIPIENT_PREFIX': 'recipient'},
        'type': mock_rule(),
        'filter': [{'query': {'query_string': {'query': '*hihi*'}}}],
        'alert': 'opsgenie',
        'opsgenie_teams': ['{TEAM_PREFIX}-Team'],
        'opsgenie_teams_args': {'TEAM_PREFIX': 'team'},
        'opsgenie_default_teams': ["Test"]
    }
    match = [
        {
            '@timestamp': '2014-10-10T00:00:00',
            'sender_ip': '1.1.1.1',
            'hostname': 'aProbe'
        },
        {
            '@timestamp': '2014-10-10T00:00:00',
            'sender_ip': '1.1.1.1',
            'hostname2': 'aProbe'
        }
    ]
    with mock.patch('requests.post'):
        alert = OpsGenieAlerter(rule)
        alert.alert([{'@timestamp': '2014-10-31T00:00:00', 'team': "Test"}])
        actual = alert._parse_responders(
            rule['opsgenie_teams'],
            rule['opsgenie_teams_args'],
            match,
            rule['opsgenie_default_teams']
        )
    excepted = ['Test']
    assert excepted == actual
    user, level, message = caplog.record_tuples[0]
    assert logging.WARNING == level
    assert "Cannot create responder for OpsGenie Alert. Key not foud: 'RECEIPIENT_PREFIX'." in message
    user, level, message = caplog.record_tuples[1]
    assert logging.WARNING == level
    assert 'no responders can be formed. Trying the default responder' in message
    user, level, message = caplog.record_tuples[2]
    assert logging.WARNING == level
    assert 'default responder not set. Falling back' in message
    user, level, message = caplog.record_tuples[3]
    assert logging.WARNING == level
    assert "Cannot create responder for OpsGenie Alert. Key not foud: 'TEAM_PREFIX'." in message
    user, level, message = caplog.record_tuples[4]
    assert logging.WARNING == level
    assert 'no responders can be formed. Trying the default responder' in message
Beispiel #6
0
def test_email_with_args():
    rule = {
        'name': 'test alert',
        'email': ['*****@*****.**', '*****@*****.**'],
        'from_addr': '*****@*****.**',
        'type': mock_rule(),
        'timestamp_field': '@timestamp',
        'email_reply_to': '*****@*****.**',
        'alert_subject': 'Test alert for {0} {1}',
        'alert_subject_args': ['test_term', 'test.term'],
        'alert_text': 'Test alert for {0} and {1} {2}',
        'alert_text_args': ['test_arg1', 'test_arg2', 'test.arg3'],
        'alert_missing_value': '<CUSTOM MISSING VALUE>'
    }
    with mock.patch('elastalert.alerters.email.SMTP') as mock_smtp:
        mock_smtp.return_value = mock.Mock()

        alert = EmailAlerter(rule)
        alert.alert([{
            'test_term': 'test_value',
            'test_arg1': 'testing',
            'test': {
                'term': ':)',
                'arg3': '☃'
            }
        }])
        expected = [
            mock.call('localhost'),
            mock.call().ehlo(),
            mock.call().has_extn('STARTTLS'),
            mock.call().starttls(certfile=None, keyfile=None),
            mock.call().sendmail(mock.ANY,
                                 ['*****@*****.**', '*****@*****.**'],
                                 mock.ANY),
            mock.call().quit()
        ]
        assert mock_smtp.mock_calls == expected

        body = mock_smtp.mock_calls[4][1][2]
        # Extract the MIME encoded message body
        body_text = base64.b64decode(
            body.split('\n\n')[-1][:-1]).decode('utf-8')

        assert 'testing' in body_text
        assert '<CUSTOM MISSING VALUE>' in body_text
        assert '☃' in body_text

        assert 'Reply-To: [email protected]' in body
        assert 'To: [email protected]' in body
        assert 'From: [email protected]' in body
        assert 'Subject: Test alert for test_value :)' in body
Beispiel #7
0
def test_opsgenie_getinfo(opsgenie_account, opsgenie_recipients,
                          opsgenie_teams, expected_data):
    rule = {'name': 'Opsgenie Details', 'type': mock_rule()}
    if opsgenie_account:
        rule['opsgenie_account'] = opsgenie_account
    if opsgenie_recipients:
        rule['opsgenie_recipients'] = opsgenie_recipients
    if opsgenie_teams:
        rule['opsgenie_teams'] = opsgenie_teams

    alert = OpsGenieAlerter(rule)

    actual_data = alert.get_info()
    assert expected_data == actual_data
Beispiel #8
0
def test_opsgenie_details_with_non_string_field():
    rule = {
        'name': 'Opsgenie Details',
        'type': mock_rule(),
        'opsgenie_account': 'genies',
        'opsgenie_key': 'ogkey',
        'opsgenie_details': {
            'Age': {
                'field': 'age'
            },
            'Message': {
                'field': 'message'
            }
        }
    }
    match = {
        'age': 10,
        'message': {
            'format': 'The cow goes %s!',
            'arg0': 'moo'
        }
    }
    alert = OpsGenieAlerter(rule)

    with mock.patch('requests.post') as mock_post_request:
        alert.alert([match])

    mock_post_request.assert_called_once_with(
        'https://api.opsgenie.com/v2/alerts',
        headers={
            'Content-Type': 'application/json',
            'Authorization': 'GenieKey ogkey'
        },
        json=mock.ANY,
        proxies=None)

    expected_json = {
        'description': BasicMatchString(rule, match).__str__(),
        'details': {
            'Age': '10',
            'Message': "{'format': 'The cow goes %s!', 'arg0': 'moo'}"
        },
        'message': 'ElastAlert: Opsgenie Details',
        'priority': None,
        'source': 'ElastAlert',
        'tags': ['ElastAlert', 'Opsgenie Details'],
        'user': '******'
    }
    actual_json = mock_post_request.call_args_list[0][1]['json']
    assert expected_json == actual_json
Beispiel #9
0
def test_msend_service_slotsetvalues_string_type():
    rule = {
        'type': mock_rule(),
        'alert_subject': 'Alert Subject',
        'alert_text': 'Alert Text',
        'msend_service_url' : 'http://www.example.com/',
        'msend_cell_name': 'somecellname',
        'msend_event_class': 'EVENT',
        'msend_event_severity': 'WARNING',
        'msend_slotsetvalues' : 'mc_host=testhost;mc_tool=Elasticsearch;mc_object=test object;mc_object_class=test object class;mc_parameter=test parameter;mc_parameter_value=test parameter value',
    }
    match = {'@timestamp': '2014-01-01T00:00:00',
         'somefield': 'foobarbaz',
         'nested': {'field': 1}}
    with pytest.raises(EAException):
        alert = MSendServiceAlerter(rule)
Beispiel #10
0
def test_msend_mandatory_params():
    rule = {
        'type': mock_rule(),
        'alert_subject': 'Alert Subject',
        'alert_text': 'Alert Text',
        'msend_cell_name': 'somecellname',
        'msend_event_class': 'EVENT',
        'msend_event_severity': 'WARNING',
    }
    alert = MSendAlerter(rule)
    match = {'@timestamp': '2014-01-01T00:00:00',
             'somefield': 'foobarbaz',
             'nested': {'field': 1}}
    with mock.patch("elastalert_modules.cx_alerters.subprocess.Popen") as mock_popen:
        alert.alert([match])
    mock_popen.assert_called_with("/opt/msend/bin/msend -l /opt/msend -n somecellname -a EVENT -r WARNING -m 'Alert Subject'", stdin=subprocess.PIPE, shell=True)
Beispiel #11
0
def test_opsgenie_tags():
    rule = {
        'name': 'Opsgenie Details',
        'type': mock_rule(),
        'opsgenie_account': 'genies',
        'opsgenie_key': 'ogkey',
        'opsgenie_details': {
            'Message': {'field': 'message'},
            'Missing': {'field': 'missing'}
        },
        'opsgenie_tags': ['{somefield}', 'test2']
    }

    alert = OpsGenieAlerter(rule)
    validateAlertTag(alert, rule, 'somevalue')
    validateAlertTag(alert, rule, 'anothervalue')
Beispiel #12
0
def test_opsgenie_required_error(opsgenie_key, expected_data):
    try:
        rule = {
            'name': 'Opsgenie Details',
            'type': mock_rule(),
        }

        if opsgenie_key:
            rule['opsgenie_key'] = opsgenie_key

        alert = OpsGenieAlerter(rule)

        actual_data = alert.get_info()
        assert expected_data == actual_data
    except Exception as ea:
        assert expected_data in str(ea)
Beispiel #13
0
def test_msend_slotsetvalues_string_type():
    rule = {
        'type': mock_rule(),
        'alert_subject': 'Alert Subject',
        'alert_text': 'Alert Text',
        'msend_cell_name': 'somecellname',
        'msend_event_class': 'EVENT',
        'msend_event_severity': 'WARNING',
        'msend_slotsetvalues' : 'mc_host=testhost;mc_tool=Elasticsearch;mc_object=test object;mc_object_class=test object class;mc_parameter=test parameter;mc_parameter_value=test parameter value',
    }
    match = {'@timestamp': '2014-01-01T00:00:00',
         'somefield': 'foobarbaz',
         'nested': {'field': 1}}
    alert = MSendAlerter(rule)
    with mock.patch("elastalert_modules.cx_alerters.subprocess.Popen") as mock_popen:
        alert.alert([match])
    mock_popen.assert_called_with("/opt/msend/bin/msend -l /opt/msend -n somecellname -a EVENT -r WARNING -m 'Alert Subject' -b 'mc_host=testhost;mc_tool=Elasticsearch;mc_object=test object;mc_object_class=test object class;mc_parameter=test parameter;mc_parameter_value=test parameter value'", stdin=subprocess.PIPE, shell=True)
Beispiel #14
0
def test_opsgenie_subject_args():
    rule = {
        'name': 'Opsgenie Details',
        'type': mock_rule(),
        'opsgenie_account': 'genies',
        'opsgenie_key': 'ogkey',
        'opsgenie_details': {
            'Message': {
                'field': 'message'
            },
            'Missing': {
                'field': 'missing'
            }
        },
        'opsgenie_subject': 'test',
        'opsgenie_subject_args': ['Testing', 'message']
    }
    match = {'message': 'Testing', '@timestamp': '2014-10-31T00:00:00'}
    alert = OpsGenieAlerter(rule)

    with mock.patch('requests.post') as mock_post_request:
        alert.alert([match])

    mock_post_request.assert_called_once_with(
        'https://api.opsgenie.com/v2/alerts',
        headers={
            'Content-Type': 'application/json',
            'Authorization': 'GenieKey ogkey'
        },
        json=mock.ANY,
        proxies=None)

    expected_json = {
        'description': BasicMatchString(rule, match).__str__(),
        'details': {
            'Message': 'Testing'
        },
        'message': 'test',
        'priority': None,
        'source': 'ElastAlert',
        'tags': ['ElastAlert', 'Opsgenie Details'],
        'user': '******'
    }
    actual_json = mock_post_request.call_args_list[0][1]['json']
    assert expected_json == actual_json
Beispiel #15
0
def test_http_post_mandatory_params():
    # Posting - only mandatory parameters
    alert = None
    rule = {
        'type': mock_rule(),
        'name': 'Test HTTP Post Rule',
        'http_post_url' : 'http://www.example.com/endpoint',
    }
    match = {'@timestamp': '2014-01-01T00:00:00',
         'somefield': 'foobarbaz',
         'nested': {'field': 1}}
    alert = HttpPostAlerter(rule)

    expected_data = '{"matches": [{"@timestamp": "2014-01-01T00:00:00", "somefield": "foobarbaz", "nested": {"field": 1}}], "rule": "Test HTTP Post Rule"}'
    expected_headers = {'Content-Type': 'application/json', 'Accept': 'application/json;charset=utf-8'}
    with mock.patch("elastalert_modules.cx_alerters.requests.post") as mock_request:
        alert.alert([match])
    mock_request.assert_called_with('http://www.example.com/endpoint', data=expected_data, headers=expected_headers)
Beispiel #16
0
def test_esalerter_init_validation():
    # All mandatory fields present 
    rule = {
        'type': mock_rule(),
        'name': 'Test ElastSearchAlerter Rule',
        'es_host': '127.0.0.1',
        'es_port': '9200',
        'esalerter_index' : 'logstash-example',
        'esalerter_document_type': 'example',
        'esalerter_data' : {
            'field1' : '{field1}',
            'field2' : '{field2}'
        }

    }
    alert = ElasticSearchAlerter(rule)
    assert alert is not None

    
Beispiel #17
0
def test_msend_service_mandatory_params():
    rule = {
        'type': mock_rule(),
        'alert_subject': 'Alert Subject',
        'alert_text': 'Alert Text',
        'msend_service_url' : 'http://www.example.com/',
        'msend_cell_name': 'somecellname',
        'msend_event_class': 'EVENT',
        'msend_event_severity': 'WARNING',
    }
    alert = MSendServiceAlerter(rule)
    match = {'@timestamp': '2014-01-01T00:00:00',
             'somefield': 'foobarbaz',
             'nested': {'field': 1}}
    expected_headers = {'Content-Type': 'application/json', 'Accept': 'application/json;charset=utf-8'}
    expected_data = '{"msend_event_severity": "WARNING", "msend_cell_name": "somecellname", "msend_event_message": "Alert Subject", "msend_event_class": "EVENT"}'
    with mock.patch("elastalert_modules.cx_alerters.requests.post") as mock_post:
        alert.alert([match])
    mock_post.assert_called_with('http://www.example.com/', headers = expected_headers, data = expected_data)
Beispiel #18
0
def test_email_from_field(email_from_field, email_add_domain, match_data,
                          expected_data):
    rule = {
        'name': 'test alert',
        'email': ['*****@*****.**'],
        'email_add_domain': 'example.com',
        'type': mock_rule(),
        'timestamp_field': '@timestamp',
        'email_from_field': 'data.user',
        'owner': 'owner_value'
    }
    if email_from_field:
        rule['email_from_field'] = email_from_field
    if email_add_domain:
        rule['email_add_domain'] = email_add_domain
    with mock.patch('elastalert.alerters.email.SMTP') as mock_smtp:
        mock_smtp.return_value = mock.Mock()
        alert = EmailAlerter(rule)
        alert.alert(match_data)
        assert mock_smtp.mock_calls[4][1][1] == expected_data
Beispiel #19
0
def test_opsgenie_alert_routing():
    rule = {
        'name': 'testOGalert',
        'opsgenie_key': 'ogkey',
        'opsgenie_account': 'genies',
        'opsgenie_addr': 'https://api.opsgenie.com/v2/alerts',
        'opsgenie_recipients': ['{RECEIPIENT_PREFIX}'],
        'opsgenie_recipients_args': {'RECEIPIENT_PREFIX': 'recipient'},
        'type': mock_rule(),
        'filter': [{'query': {'query_string': {'query': '*hihi*'}}}],
        'alert': 'opsgenie',
        'opsgenie_teams': ['{TEAM_PREFIX}-Team'],
        'opsgenie_teams_args': {'TEAM_PREFIX': 'team'}
    }
    with mock.patch('requests.post'):

        alert = OpsGenieAlerter(rule)
        alert.alert([{'@timestamp': '2014-10-31T00:00:00', 'team': "Test", 'recipient': "lytics"}])

        assert alert.get_info()['teams'] == ['Test-Team']
        assert alert.get_info()['recipients'] == ['lytics']
Beispiel #20
0
def test_msend_slotsetvalues_dict_variable_subst_oldstrformat():
    rule = {
        'type': mock_rule(),
        'alert_subject': 'Alert Subject',
        'alert_text': 'Alert Text',
        'msend_cell_name': 'somecellname',
        'msend_event_class': 'EVENT',
        'msend_event_severity': 'WARNING',
        'msend_slotsetvalues' : {
            'mc_host': 'testhost',
            'mc_tool': 'Elasticsearch',
            'mc_long_msg': '%(somefield)s',
       	}
    }
    match = {'@timestamp': '2014-01-01T00:00:00',
         'somefield': 'foobarbaz',
         'nested': {'field': 1}}
    alert = MSendAlerter(rule)
    with mock.patch("elastalert_modules.cx_alerters.subprocess.Popen") as mock_popen:
        alert.alert([match])
    mock_popen.assert_called_with("/opt/msend/bin/msend -l /opt/msend -n somecellname -a EVENT -r WARNING -m 'Alert Subject' -b 'mc_long_msg=foobarbaz;mc_tool=Elasticsearch;mc_host=testhost'", stdin=subprocess.PIPE, shell=True)
Beispiel #21
0
def test_email_getinfo():
    rule = {
        'name': 'test alert',
        'email': ['*****@*****.**', '*****@*****.**'],
        'from_addr': '*****@*****.**',
        'type': mock_rule(),
        'timestamp_field': '@timestamp',
        'email_reply_to': '*****@*****.**',
        'owner': 'owner_value',
        'alert_subject': 'Test alert for {0}, owned by {1}',
        'alert_subject_args': ['test_term', 'owner'],
        'snowman': '☃'
    }
    alert = EmailAlerter(rule)

    expected_data = {
        'type': 'email',
        'recipients': ['*****@*****.**', '*****@*****.**']
    }
    actual_data = alert.get_info()
    assert expected_data == actual_data
Beispiel #22
0
def test_email(caplog):
    caplog.set_level(logging.INFO)
    rule = {
        'name': 'test alert',
        'email': ['*****@*****.**', '*****@*****.**'],
        'from_addr': '*****@*****.**',
        'type': mock_rule(),
        'timestamp_field': '@timestamp',
        'email_reply_to': '*****@*****.**',
        'owner': 'owner_value',
        'alert_subject': 'Test alert for {0}, owned by {1}',
        'alert_subject_args': ['test_term', 'owner'],
        'snowman': '☃'
    }
    with mock.patch('elastalert.alerters.email.SMTP') as mock_smtp:
        mock_smtp.return_value = mock.Mock()

        alert = EmailAlerter(rule)
        alert.alert([{'test_term': 'test_value'}])
        expected = [
            mock.call('localhost'),
            mock.call().ehlo(),
            mock.call().has_extn('STARTTLS'),
            mock.call().starttls(certfile=None, keyfile=None),
            mock.call().sendmail(mock.ANY,
                                 ['*****@*****.**', '*****@*****.**'],
                                 mock.ANY),
            mock.call().quit()
        ]
        assert mock_smtp.mock_calls == expected

        body = mock_smtp.mock_calls[4][1][2]

        assert 'Reply-To: [email protected]' in body
        assert 'To: [email protected]' in body
        assert 'From: [email protected]' in body
        assert 'Subject: Test alert for test_value, owned by owner_value' in body
        assert ('elastalert', logging.INFO,
                "Sent email to ['*****@*****.**', '*****@*****.**']"
                ) == caplog.record_tuples[0]
Beispiel #23
0
def test_opsgenie_details_with_environment_variable_replacement(environ):
    environ.update({
        'TEST_VAR': 'Bar'
    })
    rule = {
        'name': 'Opsgenie Details',
        'type': mock_rule(),
        'opsgenie_account': 'genies',
        'opsgenie_key': 'ogkey',
        'opsgenie_details': {'Foo': '$TEST_VAR'}
    }
    match = {
        '@timestamp': '2014-10-31T00:00:00'
    }
    alert = OpsGenieAlerter(rule)

    with mock.patch('requests.post') as mock_post_request:
        alert.alert([match])

    mock_post_request.assert_called_once_with(
        'https://api.opsgenie.com/v2/alerts',
        headers={
            'Content-Type': 'application/json',
            'Authorization': 'GenieKey ogkey'
        },
        json=mock.ANY,
        proxies=None
    )

    expected_json = {
        'description': BasicMatchString(rule, match).__str__(),
        'details': {'Foo': 'Bar'},
        'message': 'ElastAlert: Opsgenie Details',
        'priority': None,
        'source': 'ElastAlert',
        'tags': ['ElastAlert', 'Opsgenie Details'],
        'user': '******'
    }
    actual_json = mock_post_request.call_args_list[0][1]['json']
    assert expected_json == actual_json
Beispiel #24
0
def test_email_smtp_exception():
    with pytest.raises(EAException) as ea:
        rule = {
            'name': 'test alert',
            'email': ['*****@*****.**', '*****@*****.**'],
            'from_addr': '*****@*****.**',
            'type': mock_rule(),
            'timestamp_field': '@timestamp',
            'email_reply_to': '*****@*****.**',
            'alert_subject': 'Test alert for {0}',
            'alert_subject_args': ['test_term'],
            'smtp_auth_file': 'file.txt',
            'rule_file': '/tmp/foo.yaml'
        }
        with mock.patch('elastalert.alerters.email.SMTP_SSL'):
            with mock.patch('elastalert.alerts.read_yaml') as mock_open:
                mock_open.return_value = {
                    'user': '******',
                    'password': '******'
                }
                alert = EmailAlerter(rule)
                alert.alert([{'test_term': 'test_value'}])
    assert 'Error connecting to SMTP host: ' in str(ea)
Beispiel #25
0
def test_email_key_error(email, expected_data):
    try:
        rule = {
            'name': 'test alert',
            'from_addr': '*****@*****.**',
            'type': mock_rule(),
            'timestamp_field': '@timestamp',
            'email_reply_to': '*****@*****.**',
            'owner': 'owner_value',
            'alert_subject': 'Test alert for {0}, owned by {1}',
            'alert_subject_args': ['test_term', 'owner'],
            'snowman': '☃'
        }

        if email:
            rule['email'] = email

        alert = EmailAlerter(rule)

        actual_data = alert.get_info()
        assert expected_data == actual_data
    except Exception:
        assert expected_data
Beispiel #26
0
def test_email_format_html():
    rule = {
        'name': 'test alert',
        'email': ['*****@*****.**', '*****@*****.**'],
        'smtp_ssl': True,
        'smtp_port': 455,
        'email_format': 'html',
        'from_addr': '*****@*****.**',
        'type': mock_rule(),
        'timestamp_field': '@timestamp',
        'email_reply_to': '*****@*****.**',
        'owner': 'owner_value',
        'alert_subject': 'Test alert for {0}, owned by {1}',
        'alert_subject_args': ['test_term', 'owner'],
        'snowman': '☃'
    }
    with mock.patch('elastalert.alerters.email.SMTP_SSL') as mock_smtp:
        mock_smtp.return_value = mock.Mock()

        alert = EmailAlerter(rule)
        alert.alert([{'test_term': 'test_value'}])
        expected = [
            mock.call('localhost', 455, certfile=None, keyfile=None),
            mock.call().sendmail(mock.ANY,
                                 ['*****@*****.**', '*****@*****.**'],
                                 mock.ANY),
            mock.call().quit()
        ]
        assert mock_smtp.mock_calls == expected

        body = mock_smtp.mock_calls[1][1][2]

        assert 'Reply-To: [email protected]' in body
        assert 'To: [email protected]' in body
        assert 'From: [email protected]' in body
        assert 'Subject: Test alert for test_value, owned by owner_value' in body
        assert 'Content-Type: text/html; charset="utf-8"' in body
Beispiel #27
0
def test_opsgenie_get_details2():
    rule = {
        'name': 'Opsgenie Details',
        'type': mock_rule(),
        'opsgenie_account': 'genies',
        'opsgenie_key': 'ogkey',
        'Testing': 'abc',
        'opsgenie_subject': '{} {} {}',
        'opsgenie_subject_args': ['Testing', 'message', '@timestamp']
    }
    match = [
        {
            'message': 'Testing',
            '@timestamp': '2014-10-31T00:00:00'
        },
        {
            'message': 'Testing',
            '@timestamp': '2014-10-31T00:00:00'
        }
    ]
    alert = OpsGenieAlerter(rule)
    actual = alert.get_details(match)
    excepted = {}
    assert excepted == actual
Beispiel #28
0
def test_msend_service_slotsetvalues_dict_variable_subst_oldstrformat():
    rule = {
        'type': mock_rule(),
        'alert_subject': 'Alert Subject',
        'alert_text': 'Alert Text',
        'msend_service_url' : 'http://www.example.com/',
        'msend_cell_name': 'somecellname',
        'msend_event_class': 'EVENT',
        'msend_event_severity': 'WARNING',
        'msend_slotsetvalues' : {
            'mc_host': 'testhost',
            'mc_tool': 'Elasticsearch',
            'mc_long_msg': '%(somefield)s',
        }
    }
    match = {'@timestamp': '2014-01-01T00:00:00',
         'somefield': 'foobarbaz',
         'nested': {'field': 1}}
    alert = MSendServiceAlerter(rule)
    expected_headers = {'Content-Type': 'application/json', 'Accept': 'application/json;charset=utf-8'}
    expected_data = '{"msend_event_severity": "WARNING", "msend_event_slotvalues": {"mc_long_msg": "foobarbaz", "mc_host": "testhost", "mc_tool": "Elasticsearch"}, "msend_cell_name": "somecellname", "msend_event_message": "Alert Subject", "msend_event_class": "EVENT"}'
    with mock.patch("elastalert_modules.cx_alerters.requests.post") as mock_post:
        alert.alert([match])
    mock_post.assert_called_with('http://www.example.com/', headers = expected_headers, data = expected_data)
Beispiel #29
0
def test_jira(caplog):
    caplog.set_level(logging.INFO)
    description_txt = "Description stuff goes here like a runbook link."
    rule = {
        'name': 'test alert',
        'jira_account_file': 'jirafile',
        'type': mock_rule(),
        'jira_project': 'testproject',
        'jira_priority': 0,
        'jira_issuetype': 'testtype',
        'jira_server': 'jiraserver',
        'jira_label': 'testlabel',
        'jira_component': 'testcomponent',
        'jira_description': description_txt,
        'jira_watchers': ['testwatcher1', 'testwatcher2'],
        'timestamp_field': '@timestamp',
        'alert_subject': 'Issue {0} occurred at {1}',
        'alert_subject_args': ['test_term', '@timestamp'],
        'rule_file': '/tmp/foo.yaml'
    }

    mock_priority = mock.Mock(id='5')

    with mock.patch('elastalert.alerters.jira.JIRA') as mock_jira, \
            mock.patch('elastalert.alerters.jira.read_yaml') as mock_open:
        mock_open.return_value = {
            'user': '******',
            'password': '******'
        }
        mock_jira.return_value.priorities.return_value = [mock_priority]
        mock_jira.return_value.fields.return_value = []
        alert = JiraAlerter(rule)
        alert.alert([{
            'test_term': 'test_value',
            '@timestamp': '2014-10-31T00:00:00'
        }])

    expected = [
        mock.call('jiraserver', basic_auth=('jirauser', 'jirapassword')),
        mock.call().priorities(),
        mock.call().fields(),
        mock.call().create_issue(
            issuetype={'name': 'testtype'},
            priority={'id': '5'},
            project={'key': 'testproject'},
            labels=['testlabel'],
            components=[{
                'name': 'testcomponent'
            }],
            description=mock.ANY,
            summary='Issue test_value occurred at 2014-10-31T00:00:00',
        ),
        mock.call().add_watcher(mock.ANY, 'testwatcher1'),
        mock.call().add_watcher(mock.ANY, 'testwatcher2'),
    ]

    # We don't care about additional calls to mock_jira, such as __str__
    assert mock_jira.mock_calls[:6] == expected
    assert mock_jira.mock_calls[3][2]['description'].startswith(
        description_txt)
    user, level, message = caplog.record_tuples[0]
    assert 'elastalert' == user
    assert logging.INFO == level
    assert 'pened Jira ticket: ' in message

    # Search called if jira_bump_tickets
    rule['jira_bump_tickets'] = True
    with mock.patch('elastalert.alerters.jira.JIRA') as mock_jira, \
            mock.patch('elastalert.alerters.jira.read_yaml') as mock_open:
        mock_open.return_value = {
            'user': '******',
            'password': '******'
        }
        mock_jira.return_value = mock.Mock()
        mock_jira.return_value.search_issues.return_value = []
        mock_jira.return_value.priorities.return_value = [mock_priority]
        mock_jira.return_value.fields.return_value = []

        alert = JiraAlerter(rule)
        alert.alert([{
            'test_term': 'test_value',
            '@timestamp': '2014-10-31T00:00:00'
        }])

    expected.insert(3, mock.call().search_issues(mock.ANY))
    assert mock_jira.mock_calls == expected

    # Remove a field if jira_ignore_in_title set
    rule['jira_ignore_in_title'] = 'test_term'
    with mock.patch('elastalert.alerters.jira.JIRA') as mock_jira, \
            mock.patch('elastalert.alerters.jira.read_yaml') as mock_open:
        mock_open.return_value = {
            'user': '******',
            'password': '******'
        }
        mock_jira.return_value = mock.Mock()
        mock_jira.return_value.search_issues.return_value = []
        mock_jira.return_value.priorities.return_value = [mock_priority]
        mock_jira.return_value.fields.return_value = []

        alert = JiraAlerter(rule)
        alert.alert([{
            'test_term': 'test_value',
            '@timestamp': '2014-10-31T00:00:00'
        }])

    assert 'test_value' not in mock_jira.mock_calls[3][1][0]

    # Issue is still created if search_issues throws an exception
    with mock.patch('elastalert.alerters.jira.JIRA') as mock_jira, \
            mock.patch('elastalert.alerters.jira.read_yaml') as mock_open:
        mock_open.return_value = {
            'user': '******',
            'password': '******'
        }
        mock_jira.return_value = mock.Mock()
        mock_jira.return_value.search_issues.side_effect = JIRAError
        mock_jira.return_value.priorities.return_value = [mock_priority]
        mock_jira.return_value.fields.return_value = []

        alert = JiraAlerter(rule)
        alert.alert([{
            'test_term': 'test_value',
            '@timestamp': '2014-10-31T00:00:00'
        }])

    assert mock_jira.mock_calls == expected
    user, level, message = caplog.record_tuples[3]
    assert 'elastalert' in user
    assert logging.ERROR == level
    assert 'Error while searching for Jira ticket using jql' in message

    # Only bump after 3d of inactivity
    rule['jira_bump_after_inactivity'] = 3
    mock_issue = mock.Mock()

    # Check ticket is bumped if it is updated 4 days ago
    mock_issue.fields.updated = str(ts_now() - datetime.timedelta(days=4))
    with mock.patch('elastalert.alerters.jira.JIRA') as mock_jira, \
            mock.patch('elastalert.alerters.jira.read_yaml') as mock_open:
        mock_open.return_value = {
            'user': '******',
            'password': '******'
        }
        mock_jira.return_value = mock.Mock()
        mock_jira.return_value.search_issues.return_value = [mock_issue]
        mock_jira.return_value.priorities.return_value = [mock_priority]
        mock_jira.return_value.fields.return_value = []

        alert = JiraAlerter(rule)
        alert.alert([{
            'test_term': 'test_value',
            '@timestamp': '2014-10-31T00:00:00'
        }])
        # Check add_comment is called
        assert len(mock_jira.mock_calls) == 5
        assert '().add_comment' == mock_jira.mock_calls[4][0]

    # Check ticket is bumped is not bumped if ticket is updated right now
    mock_issue.fields.updated = str(ts_now())
    with mock.patch('elastalert.alerters.jira.JIRA') as mock_jira, \
            mock.patch('elastalert.alerters.jira.read_yaml') as mock_open:
        mock_open.return_value = {
            'user': '******',
            'password': '******'
        }
        mock_jira.return_value = mock.Mock()
        mock_jira.return_value.search_issues.return_value = [mock_issue]
        mock_jira.return_value.priorities.return_value = [mock_priority]
        mock_jira.return_value.fields.return_value = []

        alert = JiraAlerter(rule)
        alert.alert([{
            'test_term': 'test_value',
            '@timestamp': '2014-10-31T00:00:00'
        }])
        # Only 4 calls for mock_jira since add_comment is not called
        assert len(mock_jira.mock_calls) == 4

        # Test match resolved values
        rule = {
            'name': 'test alert',
            'jira_account_file': 'jirafile',
            'type': mock_rule(),
            'owner': 'the_owner',
            'jira_project': 'testproject',
            'jira_issuetype': 'testtype',
            'jira_server': 'jiraserver',
            'jira_label': 'testlabel',
            'jira_component': 'testcomponent',
            'jira_description': "DESC",
            'jira_watchers': ['testwatcher1', 'testwatcher2'],
            'timestamp_field': '@timestamp',
            'jira_affected_user': "******",
            'rule_file': '/tmp/foo.yaml'
        }
        mock_issue = mock.Mock()
        mock_issue.fields.updated = str(ts_now() - datetime.timedelta(days=4))
        mock_fields = [{
            'name': 'affected user',
            'id': 'affected_user_id',
            'schema': {
                'type': 'string'
            }
        }]
        with mock.patch('elastalert.alerters.jira.JIRA') as mock_jira, \
                mock.patch('elastalert.alerters.jira.read_yaml') as mock_open:
            mock_open.return_value = {
                'user': '******',
                'password': '******'
            }
            mock_jira.return_value = mock.Mock()
            mock_jira.return_value.search_issues.return_value = [mock_issue]
            mock_jira.return_value.fields.return_value = mock_fields
            mock_jira.return_value.priorities.return_value = [mock_priority]
            alert = JiraAlerter(rule)
            alert.alert([{
                'gmail.the_user': '******',
                '@timestamp': '2014-10-31T00:00:00'
            }])
            assert mock_jira.mock_calls[4][2]['affected_user_id'] == "jdoe"
Beispiel #30
0
def test_jira_arbitrary_field_support():
    description_txt = "Description stuff goes here like a runbook link."
    rule = {
        'name':
        'test alert',
        'jira_account_file':
        'jirafile',
        'type':
        mock_rule(),
        'owner':
        'the_owner',
        'jira_project':
        'testproject',
        'jira_issuetype':
        'testtype',
        'jira_server':
        'jiraserver',
        'jira_label':
        'testlabel',
        'jira_component':
        'testcomponent',
        'jira_description':
        description_txt,
        'jira_watchers': ['testwatcher1', 'testwatcher2'],
        'jira_arbitrary_reference_string_field':
        '$owner$',
        'jira_arbitrary_string_field':
        'arbitrary_string_value',
        'jira_arbitrary_string_array_field':
        ['arbitrary_string_value1', 'arbitrary_string_value2'],
        'jira_arbitrary_string_array_field_provided_as_single_value':
        'arbitrary_string_value_in_array_field',
        'jira_arbitrary_number_field':
        1,
        'jira_arbitrary_number_array_field': [2, 3],
        'jira_arbitrary_number_array_field_provided_as_single_value':
        1,
        'jira_arbitrary_complex_field':
        'arbitrary_complex_value',
        'jira_arbitrary_complex_array_field':
        ['arbitrary_complex_value1', 'arbitrary_complex_value2'],
        'jira_arbitrary_complex_array_field_provided_as_single_value':
        'arbitrary_complex_value_in_array_field',
        'timestamp_field':
        '@timestamp',
        'alert_subject':
        'Issue {0} occurred at {1}',
        'alert_subject_args': ['test_term', '@timestamp'],
        'rule_file':
        '/tmp/foo.yaml'
    }

    mock_priority = mock.MagicMock(id='5')

    mock_fields = [
        {
            'name': 'arbitrary reference string field',
            'id': 'arbitrary_reference_string_field',
            'schema': {
                'type': 'string'
            }
        },
        {
            'name': 'arbitrary string field',
            'id': 'arbitrary_string_field',
            'schema': {
                'type': 'string'
            }
        },
        {
            'name': 'arbitrary string array field',
            'id': 'arbitrary_string_array_field',
            'schema': {
                'type': 'array',
                'items': 'string'
            }
        },
        {
            'name': 'arbitrary string array field provided as single value',
            'id': 'arbitrary_string_array_field_provided_as_single_value',
            'schema': {
                'type': 'array',
                'items': 'string'
            }
        },
        {
            'name': 'arbitrary number field',
            'id': 'arbitrary_number_field',
            'schema': {
                'type': 'number'
            }
        },
        {
            'name': 'arbitrary number array field',
            'id': 'arbitrary_number_array_field',
            'schema': {
                'type': 'array',
                'items': 'number'
            }
        },
        {
            'name': 'arbitrary number array field provided as single value',
            'id': 'arbitrary_number_array_field_provided_as_single_value',
            'schema': {
                'type': 'array',
                'items': 'number'
            }
        },
        {
            'name': 'arbitrary complex field',
            'id': 'arbitrary_complex_field',
            'schema': {
                'type': 'ArbitraryType'
            }
        },
        {
            'name': 'arbitrary complex array field',
            'id': 'arbitrary_complex_array_field',
            'schema': {
                'type': 'array',
                'items': 'ArbitraryType'
            }
        },
        {
            'name': 'arbitrary complex array field provided as single value',
            'id': 'arbitrary_complex_array_field_provided_as_single_value',
            'schema': {
                'type': 'array',
                'items': 'ArbitraryType'
            }
        },
    ]

    with mock.patch('elastalert.alerters.jira.JIRA') as mock_jira, \
            mock.patch('elastalert.alerters.jira.read_yaml') as mock_open:
        mock_open.return_value = {
            'user': '******',
            'password': '******'
        }
        mock_jira.return_value.priorities.return_value = [mock_priority]
        mock_jira.return_value.fields.return_value = mock_fields
        alert = JiraAlerter(rule)
        alert.alert([{
            'test_term': 'test_value',
            '@timestamp': '2014-10-31T00:00:00'
        }])

    expected = [
        mock.call('jiraserver', basic_auth=('jirauser', 'jirapassword')),
        mock.call().priorities(),
        mock.call().fields(),
        mock.call().create_issue(
            issuetype={'name': 'testtype'},
            project={'key': 'testproject'},
            labels=['testlabel'],
            components=[{
                'name': 'testcomponent'
            }],
            description=mock.ANY,
            summary='Issue test_value occurred at 2014-10-31T00:00:00',
            arbitrary_reference_string_field='the_owner',
            arbitrary_string_field='arbitrary_string_value',
            arbitrary_string_array_field=[
                'arbitrary_string_value1', 'arbitrary_string_value2'
            ],
            arbitrary_string_array_field_provided_as_single_value=[
                'arbitrary_string_value_in_array_field'
            ],
            arbitrary_number_field=1,
            arbitrary_number_array_field=[2, 3],
            arbitrary_number_array_field_provided_as_single_value=[1],
            arbitrary_complex_field={'name': 'arbitrary_complex_value'},
            arbitrary_complex_array_field=[{
                'name': 'arbitrary_complex_value1'
            }, {
                'name': 'arbitrary_complex_value2'
            }],
            arbitrary_complex_array_field_provided_as_single_value=[{
                'name':
                'arbitrary_complex_value_in_array_field'
            }],
        ),
        mock.call().add_watcher(mock.ANY, 'testwatcher1'),
        mock.call().add_watcher(mock.ANY, 'testwatcher2'),
    ]

    # We don't care about additional calls to mock_jira, such as __str__
    assert mock_jira.mock_calls[:6] == expected
    assert mock_jira.mock_calls[3][2]['description'].startswith(
        description_txt)

    # Reference an arbitrary string field that is not defined on the Jira server
    rule['jira_nonexistent_field'] = 'nonexistent field value'

    with mock.patch('elastalert.alerters.jira.JIRA') as mock_jira, \
            mock.patch('elastalert.alerters.jira.read_yaml') as mock_open:
        mock_open.return_value = {
            'user': '******',
            'password': '******'
        }
        mock_jira.return_value.priorities.return_value = [mock_priority]
        mock_jira.return_value.fields.return_value = mock_fields

        with pytest.raises(Exception) as exception:
            alert = JiraAlerter(rule)
            alert.alert([{
                'test_term': 'test_value',
                '@timestamp': '2014-10-31T00:00:00'
            }])
        assert "Could not find a definition for the jira field 'nonexistent field'" in str(
            exception)

    del rule['jira_nonexistent_field']

    # Reference a watcher that does not exist
    rule['jira_watchers'] = 'invalid_watcher'

    with mock.patch('elastalert.alerters.jira.JIRA') as mock_jira, \
            mock.patch('elastalert.alerters.jira.read_yaml') as mock_open:
        mock_open.return_value = {
            'user': '******',
            'password': '******'
        }
        mock_jira.return_value.priorities.return_value = [mock_priority]
        mock_jira.return_value.fields.return_value = mock_fields

        # Cause add_watcher to raise, which most likely means that the user did not exist
        mock_jira.return_value.add_watcher.side_effect = Exception()

        with pytest.raises(Exception) as exception:
            alert = JiraAlerter(rule)
            alert.alert([{
                'test_term': 'test_value',
                '@timestamp': '2014-10-31T00:00:00'
            }])
        assert "Exception encountered when trying to add 'invalid_watcher' as a watcher. Does the user exist?" in str(
            exception)