Exemple #1
0
    def run(self):

        api = Client(endpoint=OPTIONS['endpoint'], key=OPTIONS['key'])
        keep_alive = 0

        while not self.should_stop:
            for alertid in on_hold.keys():
                try:
                    (alert, hold_time) = on_hold[alertid]
                except KeyError:
                    continue
                if time.time() > hold_time:
                    self.send_email(alert)
                    try:
                        del on_hold[alertid]
                    except KeyError:
                        continue

            if keep_alive >= 10:
                tag = OPTIONS['smtp_host'] or 'alerta-mailer'
                try:
                    api.heartbeat(tags=[tag])
                except Exception as e:
                    time.sleep(5)
                    continue
                keep_alive = 0
            keep_alive += 1
            time.sleep(2)
    def senddata(self, content):
        config_file = os.environ.get('ALERTA_CONF_FILE') or OPTIONS['config_file']
        config = configparser.RawConfigParser(defaults=OPTIONS)
        try:
            config.read(os.path.expanduser(config_file))
        except Exception:
            sys.exit("Problem reading configuration file %s - is this an ini file?" % config_file)

        want_profile = os.environ.get('ALERTA_DEFAULT_PROFILE') or config.defaults().get('profile')
        if want_profile and config.has_section('profile %s' % want_profile):
            for opt in OPTIONS:
                try:
                    OPTIONS[opt] = config.getboolean('profile %s' % want_profile, opt)
                except (ValueError, AttributeError):
                    OPTIONS[opt] = config.get('profile %s' % want_profile, opt)
        else:
            for opt in OPTIONS:
                try:
                    OPTIONS[opt] = config.getboolean('DEFAULT', opt)
                except (ValueError, AttributeError):
                    OPTIONS[opt] = config.get('DEFAULT', opt)
        try:
            LOG.debug("[alerta] sendto=%s ", OPTIONS.get("endpoint"))
            api = Client(endpoint=OPTIONS.get("endpoint"), key=OPTIONS.get("key"), ssl_verify=OPTIONS.get("sslverify"))
            api.send_alert(**content)
        except RequestException as e:
            raise EAException("send message has error: %s" % e)

        elastalert_logger.info("send msg success" )
Exemple #3
0
    def __init__(self):

        self.api = Client()

        LOG.info('Starting UDP listener...')
        # Set up syslog UDP listener
        try:
            self.udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            self.udp.bind(('', SYSLOG_UDP_PORT))
        except socket.error as e:
            LOG.error('Syslog UDP error: %s', e)
            sys.exit(2)
        LOG.info('Listening on syslog port %s/udp' % SYSLOG_UDP_PORT)

        LOG.info('Starting TCP listener...')
        # Set up syslog TCP listener
        try:
            self.tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.tcp.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            self.tcp.bind(('', SYSLOG_TCP_PORT))
            self.tcp.listen(5)
        except socket.error as e:
            LOG.error('Syslog TCP error: %s', e)
            sys.exit(2)
        LOG.info('Listening on syslog port %s/tcp' % SYSLOG_TCP_PORT)

        self.shuttingdown = False
Exemple #4
0
    def run(self):

        endpoint = os.environ.get('ALERTA_ENDPOINT', 'http://localhost:8080')
        key = os.environ.get('ALERTA_API_KEY', None)

        self.api = Client(endpoint=endpoint, key=key)

        data = sys.stdin.read()
        LOG.info('snmptrapd -> %r', data)
        data = unicode(data, 'utf-8', errors='ignore')
        LOG.debug('unicoded -> %s', data)

        snmptrapAlert = SnmpTrapHandler.parse_snmptrap(data)

        if snmptrapAlert:
            try:
                self.api.send(snmptrapAlert)
            except Exception as e:
                LOG.warning('Failed to send alert: %s', e)

        LOG.debug('Send heartbeat...')
        try:
            origin = '{}/{}'.format('snmptrap', platform.uname()[1])
            self.api.heartbeat(origin, tags=[__version__])
        except Exception as e:
            LOG.warning('Failed to send heartbeat: %s', e)
Exemple #5
0
    def run(self):

        api = Client(endpoint=OPTIONS['endpoint'], key=OPTIONS['key'])
        keep_alive = 0

        while not self.should_stop:
            for alertid in list(on_hold.keys()):
                try:
                    (alert, hold_time) = on_hold[alertid]
                except KeyError:
                    continue

                if time.time() > hold_time:
                    self.diagnose(alert)
                    try:
                        del on_hold[alertid]
                    except KeyError:
                        continue

            if keep_alive >= 10:
                try:
                    origin = '{}'.format('alerta-trigger')
                    api.heartbeat(origin, tags=[__version__])
                except Exception as e:
                    time.sleep(5)
                    continue
                keep_alive = 0
            keep_alive += 1
            time.sleep(2)
Exemple #6
0
    def run(self):
        """Run the App main logic.

        This method should contain the core logic of the App.
        """
        alerta_api_key = self.tcex.playbook.read(self.args.alerta_api_key)
        alerta_api_endpoint = self.tcex.playbook.read(self.args.alerta_api_endpoint)
        alert_id = self.tcex.playbook.read(self.args.alert_id)
        query = self.tcex.playbook.read(self.args.query, True)

        # initialize alerta client
        client = Client(endpoint=alerta_api_endpoint, key=alerta_api_key)

        if not alert_id and not query:
            self.tcex.log.info('Retrieving all alerts from {}'.format(alerta_api_endpoint))
            alerts = client.get_alerts()
        elif alert_id:
            self.tcex.log.info('Retrieving alert with id "{}"'.format(alert_id))
            alerts = [client.get_alert(alert_id)]
        elif query:
            raise NotImplementedError('The ability to search for a query is not implemented yet. If you need it, create an issue here: https://github.com/ThreatConnect-Inc/threatconnect-playbooks/issues')
            # TODO: the difficulty here is that the query should be a tuple (I think) and I'm not sure how to (elegantly) convert the incoming string to a tuple
            # self.tcex.log.info('Retrieving alerts matching the query: {}'.format(query))
            # alerts = client.search(query)

        alerts_json = self.convert_to_json(alerts)

        self.tcex.playbook.create_output('alerta.alerts', alerts_json, 'StringArray')
        self.tcex.playbook.create_output('alerta.alerts.0', alerts_json[0], 'String')
        self.tcex.playbook.create_output('alerta.alertCount', len(alerts_json), 'String')
Exemple #7
0
    def run(self):

        api = Client(endpoint=OPTIONS['endpoint'], key=OPTIONS['key'])
        keep_alive = 0

        while not self.should_stop:
            for alertid in on_hold.keys():
                try:
                    (alert, hold_time) = on_hold[alertid]
                except KeyError:
                    continue
                if time.time() > hold_time:
                    self.send_email(alert)
                    try:
                        del on_hold[alertid]
                    except KeyError:
                        continue

            if keep_alive >= 10:
                tag = OPTIONS['smtp_host'] or 'alerta-mailer'
                try:
                    api.heartbeat(tags=[tag])
                except Exception as e:
                    time.sleep(5)
                    continue
                keep_alive = 0
            keep_alive += 1
            time.sleep(2)
Exemple #8
0
    def run(self):

        api = Client(endpoint=OPTIONS['endpoint'], key=OPTIONS['key'])
        keep_alive = 0

        while not self.should_stop:
            for alertid in list(on_hold.keys()):
                try:
                    (alert, hold_time) = on_hold[alertid]
                except KeyError:
                    continue
                if time.time() > hold_time:
                    self.send_email(alert)
                    try:
                        del on_hold[alertid]
                    except KeyError:
                        continue

            if keep_alive >= 10:
                try:
                    origin = '{}/{}'.format('alerta-mailer', OPTIONS['smtp_host'])
                    api.heartbeat(origin, tags=[__version__])
                except Exception as e:
                    time.sleep(5)
                    continue
                keep_alive = 0
            keep_alive += 1
            time.sleep(2)
Exemple #9
0
class PingerDaemon(object):
    def __init__(self):

        self.shuttingdown = False

    def run(self):

        self.running = True

        # Create internal queue
        self.queue = Queue.Queue()

        self.api = Client()

        # Initialiase ping targets
        ping_list = init_targets()

        # Start worker threads
        LOG.debug('Starting %s worker threads...', SERVER_THREAD_COUNT)
        for i in range(SERVER_THREAD_COUNT):
            w = WorkerThread(self.api, self.queue)
            try:
                w.start()
            except Exception as e:
                LOG.error('Worker thread #%s did not start: %s', i, e)
                continue
            LOG.info('Started worker thread: %s', w.getName())

        while not self.shuttingdown:
            try:
                for p in ping_list:
                    if 'targets' in p and p['targets']:
                        for target in p['targets']:
                            environment = p['environment']
                            service = p['service']
                            retries = p.get('retries', PING_MAX_RETRIES)
                            self.queue.put(
                                (environment, service, target, retries,
                                 time.time()))

                LOG.debug('Send heartbeat...')
                try:
                    origin = '{}/{}'.format('pinger', platform.uname()[1])
                    self.api.heartbeat(origin, tags=[__version__])
                except Exception as e:
                    LOG.warning('Failed to send heartbeat: %s', e)

                time.sleep(LOOP_EVERY)
                LOG.info('Ping queue length is %d', self.queue.qsize())

            except (KeyboardInterrupt, SystemExit):
                self.shuttingdown = True

        LOG.info('Shutdown request received...')
        self.running = False

        for i in range(SERVER_THREAD_COUNT):
            self.queue.put(None)
        w.join()
Exemple #10
0
class PingerDaemon(object):

    def __init__(self):

        self.shuttingdown = False

    def run(self):

        self.running = True

        # Create internal queue
        self.queue = Queue.Queue()

        self.api = Client()

        # Initialiase ping targets
        ping_list = init_targets()

        # Start worker threads
        LOG.debug('Starting %s worker threads...', SERVER_THREAD_COUNT)
        for i in range(SERVER_THREAD_COUNT):
            w = WorkerThread(self.api, self.queue)
            try:
                w.start()
            except Exception as e:
                LOG.error('Worker thread #%s did not start: %s', i, e)
                continue
            LOG.info('Started worker thread: %s', w.getName())

        while not self.shuttingdown:
            try:
                for p in ping_list:
                    if 'targets' in p and p['targets']:
                        for target in p['targets']:
                            environment = p['environment']
                            service = p['service']
                            retries = p.get('retries', PING_MAX_RETRIES)
                            self.queue.put((environment, service, target, retries, time.time()))

                LOG.debug('Send heartbeat...')
                try:
                    origin = '{}/{}'.format('pinger', platform.uname()[1])
                    self.api.heartbeat(origin, tags=[__version__])
                except Exception as e:
                    LOG.warning('Failed to send heartbeat: %s', e)

                time.sleep(LOOP_EVERY)
                LOG.info('Ping queue length is %d', self.queue.qsize())

            except (KeyboardInterrupt, SystemExit):
                self.shuttingdown = True

        LOG.info('Shutdown request received...')
        self.running = False

        for i in range(SERVER_THREAD_COUNT):
            self.queue.put(None)
        w.join()
Exemple #11
0
    def __init__(self):
        default_url = "http://localhost:8080/api"

        self.endpoint = os.environ.get("ALERTA_ENDPOINT", default_url)
        self.key = os.environ.get("ALERTA_KEY", "")
        self.ssl_verify = os.environ.get("ALERTA_SSL_VERIFY", False)

        self.client = Client(endpoint=self.endpoint,
                             key=self.key,
                             ssl_verify=self.ssl_verify)
Exemple #12
0
def main():

    api = Client()
    listener = Listener()

    while True:
        listener.send_cmd('READY\n')
        headers, body = listener.wait()
        event = headers['eventname']

        if event.startswith('TICK'):
            try:
                origin = '{}/{}'.format('supervisord', platform.uname()[1])
                api.heartbeat(origin, tags=[headers['ver'], event])
            except Exception as e:
                listener.log_stderr(e)
                listener.send_cmd('RESULT 4\nFAIL')
            else:
                listener.send_cmd('RESULT 2\nOK')
        else:
            if event.endswith('FATAL'):
                severity = 'critical'
            elif event.endswith('BACKOFF'):
                severity = 'warning'
            elif event.endswith('EXITED'):
                severity = 'minor'
            else:
                severity = 'normal'
            try:
                api.send_alert(
                    resource='%s:%s' % (platform.uname()[1], body['processname']),
                    environment='Production',
                    service=['supervisord'],
                    event=event,
                    correlate=[
                        'PROCESS_STATE_STARTING',
                        'PROCESS_STATE_RUNNING',
                        'PROCESS_STATE_BACKOFF',
                        'PROCESS_STATE_STOPPING',
                        'PROCESS_STATE_EXITED',
                        'PROCESS_STATE_STOPPED',
                        'PROCESS_STATE_FATAL',
                        'PROCESS_STATE_UNKNOWN'
                    ],
                    value='serial=%s' % headers['serial'],
                    severity=severity,
                    origin=headers['server'],
                    text='State changed from %s to %s.' % (body['from_state'], event),
                    raw_data='%s\n\n%s' % (json.dumps(headers), json.dumps(body))
                )
            except Exception as e:
                listener.log_stderr(e)
                listener.send_cmd('RESULT 4\nFAIL')
            else:
                listener.send_cmd('RESULT 2\nOK')
Exemple #13
0
    def post_receive(self, alert):
        client = Client(endpoint=FORWARD_URL)
        fw_count = alert.attributes.get('fw_count') or 0
        fw_count = fw_count + 1
        if fw_count >= FORWARD_MAX_LENGTH:
            LOG.debug('alert discarded by cycle overflow')
            return

        alert.attributes['fw_count'] = fw_count
        client.send_alert(**alert.serialize)
        return
class AlertTestCase(unittest.TestCase):

    def setUp(self):
        self.client = Client(endpoint='http://*****:*****@alerta.io')

        note = self.client.update_alert_note(alert_id, notes[0].id, text='updated note text')
        self.assertEqual(note.text, 'updated note text')

        self.client.delete_alert_note(alert_id, notes[0].id)

        notes = self.client.get_alert_notes(alert_id)
        self.assertEqual(notes, [])
    def post_receive(self, alert):
        if not FORWARD_URL or not FORWARD_API_KEY:
            return
        client = Client(endpoint=FORWARD_URL, key=FORWARD_API_KEY)
        fw_count = alert.attributes.get('fw_count') or 0
        fw_count = fw_count+1
        if fw_count >= FORWARD_MAX_LENGTH:
            LOG.debug('alert discarded by cycle overflow')
            return

        alert.attributes['fw_count'] = fw_count
        client.send_alert(
            **alert.serialize
        )
        return
    def post_receive(self, alert):
        if not FORWARD_URL or not FORWARD_API_KEY:
            return
        client = Client(endpoint=FORWARD_URL, key=FORWARD_API_KEY)
        fw_count = alert.attributes.get('fw_count') or 0
        fw_count = fw_count+1
        if fw_count >= FORWARD_MAX_LENGTH:
            LOG.debug('alert discarded by cycle overflow')
            return

        alert.get('attributes')['fw_count'] = fw_count
        client.send_alert(
            **alert
        )
        return
Exemple #17
0
class UrlmonDaemon(object):

    def __init__(self):

        self.shuttingdown = False

    def run(self):

        self.running = True

        self.queue = queue.Queue()
        self.api = Client(endpoint=settings.ENDPOINT, key=settings.API_KEY)

        # Start worker threads
        LOG.debug('Starting %s worker threads...', SERVER_THREADS)
        for i in range(SERVER_THREADS):
            w = WorkerThread(self.queue, self.api)
            try:
                w.start()
            except Exception as e:
                LOG.error('Worker thread #%s did not start: %s', i, e)
                continue
            LOG.info('Started worker thread: %s', w.getName())

        while not self.shuttingdown:
            try:
                for check in settings.checks:
                    self.queue.put((check, time.time()))

                LOG.debug('Send heartbeat...')
                try:
                    origin = '{}/{}'.format('urlmon', platform.uname()[1])
                    self.api.heartbeat(origin, tags=[__version__])
                except Exception as e:
                    LOG.warning('Failed to send heartbeat: %s', e)

                time.sleep(LOOP_EVERY)
                LOG.info('URL check queue length is %d', self.queue.qsize())

            except (KeyboardInterrupt, SystemExit):
                self.shuttingdown = True

        LOG.info('Shutdown request received...')
        self.running = False

        for i in range(SERVER_THREADS):
            self.queue.put(None)
        w.join()
Exemple #18
0
    def test_env_vars(self):

        config = Config(config_file=None)
        self.assertEqual(config.options['config_file'], '~/.alerta.conf')

        with mod_env(ALERTA_CONF_FILE='~/.alerta.test.conf',
                     ALERTA_DEFAULT_PROFILE='test-profile',
                     ALERTA_ENDPOINT='http://foo/bar/baz',
                     ALERTA_API_KEY='test-key',
                     REQUESTS_CA_BUNDLE='',
                     CLICOLOR='',
                     DEBUG='1'):

            # conf file
            config = Config(config_file=None)
            self.assertEqual(config.options['config_file'],
                             '~/.alerta.test.conf', os.environ)
            config = Config(config_file='/dev/null')
            self.assertEqual(config.options['config_file'], '/dev/null')

            # profile
            config = Config(config_file=None)
            config.get_config_for_profle()
            self.assertEqual(config.options['profile'], 'test-profile',
                             os.environ)

            # endpoint
            self.client = Client()
            self.assertEqual(self.client.endpoint, 'http://foo/bar/baz')

            # api key
            self.assertEqual(config.options['key'], 'test-key')
Exemple #19
0
    def __init__(self):

        self.api = Client()

        LOG.info('Starting UDP listener...')
        # Set up syslog UDP listener
        try:
            self.udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            self.udp.bind(('', SYSLOG_UDP_PORT))
        except socket.error as e:
            LOG.error('Syslog UDP error: %s', e)
            sys.exit(2)
        LOG.info('Listening on syslog port %s/udp' % SYSLOG_UDP_PORT)

        LOG.info('Starting TCP listener...')
        # Set up syslog TCP listener
        try:
            self.tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.tcp.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            self.tcp.bind(('', SYSLOG_TCP_PORT))
            self.tcp.listen(5)
        except socket.error as e:
            LOG.error('Syslog TCP error: %s', e)
            sys.exit(2)
        LOG.info('Listening on syslog port %s/tcp' % SYSLOG_TCP_PORT)

        self.shuttingdown = False
Exemple #20
0
def cli(ctx, config_file, profile, endpoint_url, output, color, debug):
    """
    Alerta client unified command-line tool.
    """
    config = Config(config_file)
    config.get_config_for_profle(profile)

    ctx.obj = dict()
    ctx.obj['timezone'] = config.options['timezone']
    ctx.obj['output'] = output or config.options['output']
    ctx.obj['color'] = color or os.environ.get('CLICOLOR', None) or config.options['color']
    endpoint = endpoint_url or config.options['endpoint']
    ctx.obj['provider'] = config.options['provider']
    ctx.obj['client_id'] = config.options['client_id']
    ctx.obj['github_url'] = config.options['github_url']
    ctx.obj['gitlab_url'] = config.options['gitlab_url']

    ctx.obj['client'] = Client(
        endpoint=endpoint,
        key=config.options['key'],
        token=get_token(endpoint),
        timeout=float(config.options['timeout']),
        ssl_verify=config.options['sslverify'],
        debug=debug or os.environ.get('DEBUG', None) or config.options['debug']
    )
Exemple #21
0
class ApiKeyTestCase(unittest.TestCase):

    def setUp(self):
        self.client = Client()

        self.key = """
            {
              "data": {
                "count": 0,
                "customer": null,
                "expireTime": "2018-10-03T08:36:14.651Z",
                "href": "http://localhost:8080/key/BpSG0Ck5JCqk5TJiuBSLAWuTs03QKc_527T5cDtw",
                "id": "f4203347-d1b2-4f56-b5e9-6de97cf2d8ae",
                "key": "BpSG0Ck5JCqk5TJiuBSLAWuTs03QKc_527T5cDtw",
                "lastUsedTime": null,
                "scopes": [
                  "write:alerts",
                  "admin:keys"
                ],
                "text": "Ops kAPI Key",
                "type": "read-write",
                "user": "******"
              },
              "key": "BpSG0Ck5JCqk5TJiuBSLAWuTs03QKc_527T5cDtw",
              "status": "ok"
            }
        """

    @requests_mock.mock()
    def test_key(self, m):
        m.post('http://*****:*****@example.com')
        self.assertEqual(sorted(api_key.scopes), sorted(['write:alerts', 'admin:keys']))
Exemple #22
0
class GroupTestCase(unittest.TestCase):

    def setUp(self):
        self.client = Client()

        self.key = """
            {
                "group": {
                    "count": 0,
                    "href": "http://localhost:8080/group/8ed5d256-4205-4dfc-b25d-185bd019cb21",
                    "id": "8ed5d256-4205-4dfc-b25d-185bd019cb21",
                    "name": "myGroup",
                    "text": "test group"
                },
                "id": "8ed5d256-4205-4dfc-b25d-185bd019cb21",
                "status": "ok"
            }
        """

    @requests_mock.mock()
    def test_key(self, m):
        m.post('http://localhost:8080/group', text=self.key)
        group = self.client.create_group(name='myGroup', text='test group')
        self.assertEqual(group.name, 'myGroup')
        self.assertEqual(group.text, 'test group')
    def setUp(self):
        self.client = Client()

        alarm_model = {
            'name': 'Alerta 8.0.1',
            'severity': {
                'security': 0,
                'critical': 1,
                'major': 2,
                'minor': 3,
                'warning': 4,
                'indeterminate': 5,
                'informational': 6,
                'normal': 7,
                'ok': 7,
                'cleared': 7,
                'debug': 8,
                'trace': 9,
                'unknown': 10
            },
            'defaults': {
                'normal_severity': 'normal'
            }
        }

        config = Config(config_file=None,
                        config_override={'alarm_model': alarm_model})
        self.obj = config.options
        self.obj['client'] = self.client

        self.runner = CliRunner(echo_stdin=True)
Exemple #24
0
def cli(ctx, config_file, profile, endpoint_url, output, color, debug):
    """
    Alerta client unified command-line tool.
    """
    config = Config(config_file)
    config.get_config_for_profle(profile)
    config.get_remote_config(endpoint_url)

    ctx.obj = config.options

    # override current options with command-line options or environment variables
    ctx.obj['output'] = output or config.options['output']
    ctx.obj['color'] = color or os.environ.get('CLICOLOR',
                                               None) or config.options['color']
    endpoint = endpoint_url or config.options['endpoint']

    ctx.obj['client'] = Client(endpoint=endpoint,
                               key=config.options['key'],
                               token=get_token(endpoint),
                               username=config.options.get('username', None),
                               password=config.options.get('password', None),
                               timeout=float(config.options['timeout']),
                               ssl_verify=config.options['sslverify'],
                               debug=debug or os.environ.get('DEBUG', None)
                               or config.options['debug'])
class PermissionTestCase(unittest.TestCase):

    def setUp(self):
        self.client = Client()

        self.perm = """
            {
              "id": "584f38f4-b44e-4d87-9b61-c106d21bcc7a",
              "permission": {
                "href": "http://localhost:8080/perm/584f38f4-b44e-4d87-9b61-c106d21bcc7a",
                "id": "584f38f4-b44e-4d87-9b61-c106d21bcc7a",
                "match": "websys",
                "scopes": [
                  "admin:users",
                  "admin:keys",
                  "write"
                ]
              },
              "status": "ok"
            }
        """

    @requests_mock.mock()
    def test_permission(self, m):
        m.post('http://localhost:8080/perm', text=self.perm)
        perm = self.client.create_perm(role='websys', scopes=['admin:users', 'admin:keys', 'write'])
        self.assertEqual(perm.match, 'websys')
        self.assertEqual(sorted(perm.scopes), sorted(['admin:users', 'admin:keys', 'write']))
Exemple #26
0
    def setUp(self):
        self.client = Client()

        config = Config(config_file=None)
        self.obj = config.options
        self.obj['client'] = self.client

        self.runner = CliRunner(echo_stdin=True)
Exemple #27
0
    def run(self):

        self.running = True

        self.queue = queue.Queue()
        self.api = Client(endpoint=settings.ENDPOINT, key=settings.API_KEY)

        # Start worker threads
        LOG.debug('Starting %s worker threads...', SERVER_THREADS)
        for i in range(SERVER_THREADS):
            w = WorkerThread(self.queue, self.api)
            try:
                w.start()
            except Exception as e:
                LOG.error('Worker thread #%s did not start: %s', i, e)
                continue
            LOG.info('Started worker thread: %s', w.getName())

        while not self.shuttingdown:
            try:
                for check in settings.checks:
                    self.queue.put((check, time.time()))

                LOG.debug('Send heartbeat...')
                try:
                    origin = '{}/{}'.format('urlmon', platform.uname()[1])
                    self.api.heartbeat(origin, tags=[__version__], timeout=3600)
                except Exception as e:
                    LOG.warning('Failed to send heartbeat: %s', e)

                time.sleep(LOOP_EVERY)
                LOG.info('URL check queue length is %d', self.queue.qsize())

                if self.queue.qsize() > 100:
                    severity = 'warning'
                else:
                    severity = 'ok'
                try:
                    self.api.send_alert(
                        resource=origin,
                        event='big queue for http checks',
                        value=self.queue.qsize(),
                        severity=severity,
                        text='URL check queue length is %d', self.queue.qsize(),
                        event_type='serviceAlert',
                    )
                except Exception as e:
                    LOG.warning('Failed to send alert: %s', e)

            except (KeyboardInterrupt, SystemExit):
                self.shuttingdown = True

        LOG.info('Shutdown request received...')
        self.running = False

        for i in range(SERVER_THREADS):
            self.queue.put(None)
        w.join()
Exemple #28
0
class AlertTestCase(unittest.TestCase):

    def setUp(self):
        self.client = Client(endpoint='http://api:8080', key='demo-key')

    def test_customer(self):
        customer = self.client.create_customer(customer='ACME Corp.', match='example.com')

        customer_id = customer.id

        self.assertEqual(customer.customer, 'ACME Corp.')
        self.assertEqual(customer.match, 'example.com')

        customer = self.client.update_customer(customer_id, customer='Foo Corp.', match='foo.com')

        self.assertEqual(customer.customer, 'Foo Corp.')
        self.assertEqual(customer.match, 'foo.com')

        customer = self.client.create_customer(customer='Quetzal Inc.', match='quetzal.io')

        customers = self.client.get_customers()
        self.assertEqual(len(customers), 2)

        self.client.delete_customer(customer_id)

        customers = self.client.get_customers()
        self.assertEqual(len(customers), 1)
Exemple #29
0
class AlertTestCase(unittest.TestCase):
    def setUp(self):
        self.client = Client(endpoint='http://api:8080', key='demo-key')

    def test_group(self):
        group = self.client.create_group(name='myGroup', text='test group')

        group_id = group.id

        self.assertEqual(group.name, 'myGroup')
        self.assertEqual(group.text, 'test group')

        group = self.client.update_group(group_id,
                                         name='newGroup',
                                         text='updated group text')
        self.assertEqual(group.name, 'newGroup')
        self.assertEqual(group.text, 'updated group text')

        group = self.client.create_group(name='myGroup2', text='test group2')

        groups = self.client.get_users_groups()
        self.assertEqual(len(groups), 2, groups)

        self.client.delete_group(group_id)

        groups = self.client.get_users_groups()
        self.assertEqual(len(groups), 1)
Exemple #30
0
 def alerta(self):
     """Return alerta instance, create new if missing"""
     if self._alerta is None:
         LOGGER.warning('No alerta exist. Create client.')
         self._alerta = Client(endpoint=self.alerta_config.alerta_endpoint,
                               debug=self.alerta_config.alerta_debug,
                               timeout=self.alerta_config.alerta_timeout,
                               key=self.alerta_api_key)
     return self._alerta
Exemple #31
0
class BlackoutTestCase(unittest.TestCase):
    def setUp(self):
        self.client = Client()

        self.blackout = """
            {
                "blackout": {
                    "createTime": "2021-04-14T20:36:06.453Z",
                    "customer": null,
                    "duration": 3600,
                    "endTime": "2021-04-14T21:36:06.453Z",
                    "environment": "Production",
                    "event": "node_down",
                    "group": "Network",
                    "href": "http://local.alerta.io:8080/blackout/5ed223a3-27dc-4c4c-97d1-504f107d8a1a",
                    "id": "5ed223a3-27dc-4c4c-97d1-504f107d8a1a",
                    "origin": "foo/xyz",
                    "priority": 8,
                    "remaining": 3600,
                    "resource": "web01",
                    "service": [
                      "Web",
                      "App"
                    ],
                    "startTime": "2021-04-14T20:36:06.453Z",
                    "status": "active",
                    "tags": [
                      "london",
                      "linux"
                    ],
                    "text": "Network outage in Bracknell",
                    "user": "******"
                },
                "id": "5ed223a3-27dc-4c4c-97d1-504f107d8a1a",
                "status": "ok"
            }
        """

    @requests_mock.mock()
    def test_blackout(self, m):
        m.post('http://*****:*****@alerta.dev')
Exemple #32
0
class AlertaClient(object):
    def __init__(self):
        default_url = "http://localhost:8080/api"

        self.endpoint = os.environ.get("ALERTA_ENDPOINT", default_url)
        self.key = os.environ.get("ALERTA_KEY", "")
        self.ssl_verify = os.environ.get("ALERTA_SSL_VERIFY", False)

        self.client = Client(endpoint=self.endpoint,
                             key=self.key,
                             ssl_verify=self.ssl_verify)

    def send_event(self, **event_params):
        """
        Object constructor expects nine arguments.

        :param resource: resource under alarm, deliberately not host-centric
        :param event: event name eg. NodeDown
        :param environment: effected environment, development, \
            staging or production
        :param service: list of effected services
        :param text: freeform text description
        :param value: event value eg. 100%, Down, PingFail, 55ms, ORA-1664
        :param severity: severity of alert (default normal)
        :param timeout: number of seconds before alert is considered stale
        :param raw_data: log event or the steps to resolve
        """
        if len(event_params) >= 8:
            try:
                self.client.send_alert(
                    resource=event_params.get("resource"),
                    event=event_params.get("event"),
                    environment=event_params.get("environment"),
                    service=event_params.get("service", None),
                    text=event_params.get("text"),
                    value=event_params.get("value"),
                    severity=event_params.get("severity"),
                    timeout=event_params.get("timeout", 86400),
                    raw_data=event_params.get("raw_data"),
                )
            except Exception:
                logging.error("Could not send events to alerta service",
                              exc_info=True)
class AlertTestCase(unittest.TestCase):

    def setUp(self):
        self.client = Client(endpoint='http://*****:*****@alerta.io')
        self.assertEqual(sorted(users[0].roles), sorted(['admin']))
        self.assertEqual(users[0].status, 'active')
Exemple #34
0
class AlertTestCase(unittest.TestCase):
    def setUp(self):
        self.client = Client(endpoint='http://api:8080', key='demo-key')

    def test_permission(self):
        perm = self.client.create_perm(
            role='websys', scopes=['admin:users', 'admin:keys', 'write'])
        self.assertEqual(perm.match, 'websys')
        self.assertEqual(sorted(perm.scopes),
                         sorted(['admin:users', 'admin:keys', 'write']))
Exemple #35
0
    def run(self):

        endpoint = os.environ.get('ALERTA_ENDPOINT', 'http://localhost:8080')
        key = os.environ.get('ALERTA_API_KEY', None)

        self.api = Client(endpoint=endpoint, key=key)

        data = sys.stdin.read()
        LOG.info('snmptrapd -> %r', data)
        try:
            data = unicode(data, 'utf-8', errors='ignore')  # python 2
        except NameError:
            pass
        LOG.debug('unicoded -> %s', data)

        try:
            resource, event, correlate, trap_version, trapvars = self.parse_snmptrap(data)
            if resource and event:
                self.api.send_alert(
                    resource=resource,
                    event=event,
                    correlate=correlate,
                    group='SNMP',
                    value=trapvars['$w'],
                    severity='indeterminate',
                    environment='Production',
                    service=['Network'],
                    text=trapvars['$W'],
                    event_type='snmptrapAlert',
                    attributes={'trapvars': {k.replace('$', '_'): v for k, v in trapvars.items()}},
                    tags=[trap_version],
                    create_time=datetime.datetime.strptime('%sT%s.000Z' % (trapvars['$x'], trapvars['$X']), '%Y-%m-%dT%H:%M:%S.%fZ'),
                    raw_data=data
                )
        except Exception as e:
            LOG.warning('Failed to send alert: %s', e)

        LOG.debug('Send heartbeat...')
        try:
            origin = '{}/{}'.format('snmptrap', platform.uname()[1])
            self.api.heartbeat(origin, tags=[__version__])
        except Exception as e:
            LOG.warning('Failed to send heartbeat: %s', e)
Exemple #36
0
class AlertTestCase(unittest.TestCase):
    def setUp(self):
        self.client = Client(endpoint='http://api:8080', key='demo-key')

    def test_heartbeat(self):
        hb = self.client.heartbeat(origin='app/web01',
                                   timeout=10,
                                   tags=['london', 'linux'])
        self.assertEqual(hb.origin, 'app/web01')
        self.assertEqual(hb.event_type, 'Heartbeat')
        self.assertEqual(hb.timeout, 10)
        self.assertIn('linux', hb.tags)
Exemple #37
0
class AlertTestCase(unittest.TestCase):
    def setUp(self):
        self.client = Client(endpoint='http://api:8080', key='demo-key')

    def test_alert(self):
        id, alert, message = self.client.send_alert(
            environment='Production',
            resource='net03',
            event='node_down',
            correlated=['node_up', 'node_down', 'node_marginal'],
            service=['Network', 'Core'],
            severity='critical',
            tags=['newyork', 'linux'],
            value=4)
        id, alert, message = self.client.send_alert(
            environment='Production',
            resource='net03',
            event='node_marginal',
            correlated=['node_up', 'node_down', 'node_marginal'],
            service=['Network', 'Core'],
            severity='minor',
            tags=['newyork', 'linux'],
            value=1)
        self.assertEqual(alert.value, '1')  # values cast to string
        self.assertEqual(alert.timeout, 86400)  # timeout returned as int
        self.assertIn('newyork', alert.tags)

    def test_history(self):
        hist = self.client.get_history(query=[('resource', 'net03')])
        self.assertEqual(hist[0].environment, 'Production')
        self.assertEqual(hist[0].service, ['Network', 'Core'])
        self.assertEqual(hist[0].resource, 'net03')
        self.assertIn('newyork', hist[0].tags)
        self.assertEqual(hist[0].change_type, 'new')

        self.assertEqual(hist[1].environment, 'Production')
        self.assertEqual(hist[1].service, ['Network', 'Core'])
        self.assertEqual(hist[1].resource, 'net03')
        self.assertIn('newyork', hist[1].tags)
        self.assertEqual(hist[1].change_type, 'new')
Exemple #38
0
class AlertTestCase(unittest.TestCase):
    def setUp(self):
        self.client = Client(endpoint='http://*****:*****@alerta.io')
        self.assertEqual(sorted(api_key.scopes),
                         sorted(['write:alerts', 'admin:keys']))

        api_key = self.client.update_key(api_key_id,
                                         scopes=[
                                             Scope.write_alerts,
                                             Scope.write_heartbeats,
                                             Scope.admin_keys
                                         ],
                                         text='Updated Ops API Key')
        self.assertEqual(
            sorted(api_key.scopes),
            sorted(
                [Scope.write_alerts, Scope.write_heartbeats,
                 Scope.admin_keys]))
        self.assertEqual(api_key.text, 'Updated Ops API Key')

        api_key = self.client.create_key(username='******',
                                         scopes=[Scope.admin],
                                         text='Admin API Key',
                                         key='admin-key')
        self.assertEqual(api_key.key, 'admin-key')

        api_keys = self.client.get_keys(query=[('user', '*****@*****.**')])
        self.assertEqual(len(api_keys), 2)

        api_keys = self.client.delete_key(api_key_id)
        self.assertEqual(len(api_keys), 1)
Exemple #39
0
class HistoryTestCase(unittest.TestCase):

    def setUp(self):
        self.client = Client()

        self.history = """
            {
                "history": [
                    {
                        "attributes": {
                            "ip": "127.0.0.1",
                            "notify": false
                        },
                        "customer": null,
                        "environment": "Production",
                        "event": "node_down",
                        "group": "Misc",
                        "href": "http://localhost:8080/alert/e7020428-5dad-4a41-9bfe-78e9d55cda06",
                        "id": "e7020428-5dad-4a41-9bfe-78e9d55cda06",
                        "origin": "alertad/fdaa33ca.local",
                        "resource": "web01",
                        "service": [
                            "Web",
                            "App"
                        ],
                        "severity": "critical",
                        "tags": [
                            "london",
                            "linux"
                        ],
                        "text": "",
                        "type": "severity",
                        "updateTime": "2017-10-03T09:12:27.283Z",
                        "value": "4"
                    }
                ],
                "status": "ok",
                "total": 1
            }
        """

    @requests_mock.mock()
    def test_history(self, m):
        m.get('http://localhost:8080/alerts/history', text=self.history)
        hist = self.client.get_history()
        self.assertEqual(hist[0].environment, 'Production')
        self.assertEqual(hist[0].service, ['Web', 'App'])
        self.assertEqual(hist[0].resource, 'web01')
        self.assertIn('london', hist[0].tags)
        self.assertEqual(hist[0].change_type, 'severity')
Exemple #40
0
class NotesTestCase(unittest.TestCase):

    def setUp(self):
        self.client = Client()

        self.key = """
            {
              "status": "ok"
            }
        """

    @requests_mock.mock()
    def test_add_note(self, m):
        m.put('http://localhost:8080/alert/e7020428-5dad-4a41-9bfe-78e9d55cda06/note', text=self.key)
        r = self.client.add_note(id='e7020428-5dad-4a41-9bfe-78e9d55cda06', note='this is a test note')
        self.assertEqual(r['status'], 'ok')
Exemple #41
0
class UserTestCase(unittest.TestCase):

    def setUp(self):
        self.client = Client()

        self.user = """
            {
              "domains": [
                "alerta.io",
                "gmail.com",
                "foo.com"
              ],
              "status": "ok",
              "total": 1,
              "users": [
                {
                  "attributes": {},
                  "createTime": "2017-10-01T15:45:32.671Z",
                  "domain": "alerta.io",
                  "email": "*****@*****.**",
                  "email_verified": false,
                  "href": "http://localhost:8080/user/107dcbe2-e5a9-4f6a-8c23-ce9379288bf5",
                  "id": "107dcbe2-e5a9-4f6a-8c23-ce9379288bf5",
                  "lastLogin": "******",
                  "name": "Admin",
                  "provider": "basic",
                  "roles": [
                    "admin"
                  ],
                  "status": "active",
                  "text": "",
                  "updateTime": "2017-10-03T09:21:20.888Z"
                }
              ]
            }
        """

    @requests_mock.mock()
    def test_user(self, m):
        m.get('http://localhost:8080/users', text=self.user)
        users = self.client.get_users()
        self.assertEqual(users[0].name, 'Admin')
        self.assertEqual(sorted(users[0].roles), sorted(['admin']))
        self.assertEqual(users[0].status, 'active')
class HeartbeatTestCase(unittest.TestCase):

    def setUp(self):
        self.client = Client()

        self.heartbeat = """
        {
            "heartbeat": {
                "createTime": "2017-10-02T23:54:05.214Z",
                "customer": null,
                "href": "http://localhost:8080/heartbeat/4a0b87cd-9786-48f8-9994-59a9209ff0b2",
                "id": "4a0b87cd-9786-48f8-9994-59a9209ff0b2",
                "latency": 0.0,
                "origin": "app/web01",
                "receiveTime": "2017-10-02T23:54:05.214Z",
                "since": 0,
                "status": "ok",
                "tags": [
                    "london",
                    "linux"
                ],
                "timeout": 10,
                "type": "Heartbeat"
            },
            "id": "4a0b87cd-9786-48f8-9994-59a9209ff0b2",
            "status": "ok"
        }
        """

    @requests_mock.mock()
    def test_heartbeat(self, m):
        m.post('http://localhost:8080/heartbeat', text=self.heartbeat)
        hb = self.client.heartbeat(origin='app/web01', timeout=10, tags=['london', 'linux'])
        self.assertEqual(hb.origin, 'app/web01')
        self.assertEqual(hb.event_type, 'Heartbeat')
        self.assertEqual(hb.timeout, 10)
        self.assertIn('linux', hb.tags)
Exemple #43
0
class SyslogDaemon(object):

    def __init__(self):

        self.api = Client()

        LOG.info('Starting UDP listener...')
        # Set up syslog UDP listener
        try:
            self.udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            self.udp.bind(('', SYSLOG_UDP_PORT))
        except socket.error as e:
            LOG.error('Syslog UDP error: %s', e)
            sys.exit(2)
        LOG.info('Listening on syslog port %s/udp' % SYSLOG_UDP_PORT)

        LOG.info('Starting TCP listener...')
        # Set up syslog TCP listener
        try:
            self.tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.tcp.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            self.tcp.bind(('', SYSLOG_TCP_PORT))
            self.tcp.listen(5)
        except socket.error as e:
            LOG.error('Syslog TCP error: %s', e)
            sys.exit(2)
        LOG.info('Listening on syslog port %s/tcp' % SYSLOG_TCP_PORT)

        self.shuttingdown = False

    def run(self):

        count = 0
        while not self.shuttingdown:
            try:
                LOG.debug('Waiting for syslog messages...')
                ip, op, rdy = select.select([self.udp, self.tcp], [], [], LOOP_EVERY)
                if ip:
                    for i in ip:
                        if i == self.udp:
                            data, addr = self.udp.recvfrom(4096)
                            data = unicode(data, 'utf-8', errors='ignore')
                            LOG.debug('Syslog UDP data received from %s: %s', addr, data)
                        if i == self.tcp:
                            client, addr = self.tcp.accept()
                            data = client.recv(4096)
                            data = unicode(data, 'utf-8', errors='ignore')
                            client.close()
                            LOG.debug('Syslog TCP data received from %s: %s', addr, data)

                        alerts = self.parse_syslog(ip=addr[0], data=data)
                        for alert in alerts:
                            try:
                                self.api.send_alert(**alert)
                            except Exception as e:
                                LOG.warning('Failed to send alert: %s', e)

                    count += 1
                if not ip or count % 5 == 0:
                    LOG.debug('Send heartbeat...')
                    try:
                        origin = '{}/{}'.format('syslog', platform.uname()[1])
                        self.api.heartbeat(origin, tags=[__version__])
                    except Exception as e:
                        LOG.warning('Failed to send heartbeat: %s', e)

            except (KeyboardInterrupt, SystemExit):
                self.shuttingdown = True

        LOG.info('Shutdown request received...')

    def parse_syslog(self, ip, data):

        LOG.debug('Parsing syslog message...')
        syslogAlerts = list()

        event = None
        resource = None

        for msg in data.split('\n'):
            if not msg or 'last message repeated' in msg:
                continue

            if re.match('<\d+>1', msg):
                # Parse RFC 5424 compliant message
                m = re.match(r'<(\d+)>1 (\S+) (\S+) (\S+) (\S+) (\S+) (.*)', msg)
                if m:
                    PRI = int(m.group(1))
                    ISOTIMESTAMP = m.group(2)
                    HOSTNAME = m.group(3)
                    APPNAME = m.group(4)
                    PROCID = m.group(5)
                    MSGID = m.group(6)
                    TAG = '%s[%s] %s' % (APPNAME, PROCID, MSGID)
                    MSG = m.group(7)
                    LOG.info("Parsed RFC 5424 message OK")
                else:
                    LOG.error("Could not parse RFC 5424 syslog message: %s", msg)
                    continue

            elif re.match(r'<(\d{1,3})>\S{3}\s', msg):
                # Parse RFC 3164 compliant message
                m = re.match(r'<(\d{1,3})>\S{3}\s{1,2}\d?\d \d{2}:\d{2}:\d{2} (\S+)( (\S+):)? (.*)', msg)
                if m:
                    PRI = int(m.group(1))
                    HOSTNAME = m.group(2)
                    TAG = m.group(4)
                    MSG = m.group(5)
                    LOG.info("Parsed RFC 3164 message OK")
                else:
                    LOG.error("Could not parse RFC 3164 syslog message: %s", msg)
                    continue

            elif re.match('<\d+>.*%[A-Z0-9_-]+', msg):
                # Parse Cisco Syslog message
                m = re.match('<(\d+)>.*(%([A-Z0-9_-]+)):? (.*)', msg)
                if m:
                    LOG.debug(m.groups())
                    PRI = int(m.group(1))
                    CISCO_SYSLOG = m.group(2)
                    try:
                        CISCO_FACILITY, CISCO_SEVERITY, CISCO_MNEMONIC = m.group(3).split('-')
                    except ValueError as e:
                        LOG.error('Could not parse Cisco syslog - %s: %s', e, m.group(3))
                        CISCO_FACILITY = CISCO_SEVERITY = CISCO_MNEMONIC = 'na'

                    TAG = CISCO_MNEMONIC
                    MSG = m.group(4)

                    event = CISCO_SYSLOG

                    # replace IP address with a hostname, if necessary
                    try:
                        socket.inet_aton(ip)
                        (resource, _, _) = socket.gethostbyaddr(ip)
                    except (socket.error, socket.herror):
                        resource = ip

                    resource = '%s:%s' % (resource, CISCO_FACILITY)
                else:
                    LOG.error("Could not parse Cisco syslog message: %s", msg)
                    continue

            facility, level = decode_priority(PRI)

            # Defaults
            event = event or '%s%s' % (facility.capitalize(), level.capitalize())
            resource = resource or '%s%s' % (HOSTNAME, ':' + TAG if TAG else '')
            severity = priority_to_code(level)
            group = 'Syslog'
            value = level
            text = MSG
            environment = 'Production'
            service = ['Platform']
            tags = ['%s.%s' % (facility, level)]
            correlate = ['%s%s' % (facility.capitalize(), s.capitalize()) for s in SYSLOG_SEVERITY_NAMES]
            raw_data = msg

            syslogAlert = {
                'resource': resource,
                'event': event,
                'environment': environment,
                'severity': severity,
                'correlate':correlate,
                'service': service,
                'group': group,
                'value': value,
                'text': text,
                'tags': tags,
                'event_type': 'syslogAlert',
                'raw_data': raw_data
            }
            syslogAlerts.append(syslogAlert)

        return syslogAlerts
    def setUp(self):
        self.client = Client()

        self.heartbeat = """
Exemple #45
0
    def setUp(self):
        self.client = Client()

        self.key = """
Exemple #46
0
    def setUp(self):
        self.client = Client()

        self.history = """
Exemple #47
0
    def run(self):

        while True:
            LOG.debug('Waiting on input queue...')
            try:
                check, queue_time = self.queue.get()
            except TypeError:
                LOG.info('%s is shutting down.', self.getName())
                break

            if time.time() - queue_time > LOOP_EVERY:
                LOG.warning('URL request for %s to %s expired after %d seconds.', check['resource'], check['url'],
                            int(time.time() - queue_time))
                self.queue.task_done()
                continue

            resource = check['resource']
            LOG.info('%s polling %s...', self.getName(), resource)
            status, reason, body, rtt = self.urlmon(check)

            status_regex = check.get('status_regex', None)
            search_string = check.get('search', None)
            rule = check.get('rule', None)
            warn_thold = check.get('warning', SLOW_WARNING_THRESHOLD)
            crit_thold = check.get('critical', SLOW_CRITICAL_THRESHOLD)
            checker_api = check.get('api_endpoint', None)
            checker_apikey = check.get('api_key', None)
            check_ssl = check.get('check_ssl')
            if (checker_api and checker_apikey):
                local_api = Client(endpoint=checker_api, key=checker_apikey)
            else:
                local_api = self.api

            try:
                description = HTTP_RESPONSES[status]
            except KeyError:
                description = 'undefined'

            if not status:
                event = 'HttpConnectionError'
                severity = 'major'
                value = reason
                text = 'Error during connection or data transfer (timeout=%d).' % MAX_TIMEOUT

            elif status_regex:
                if re.search(status_regex, str(status)):
                    event = 'HttpResponseRegexOK'
                    severity = 'normal'
                    value = '%s (%d)' % (description, status)
                    text = 'HTTP server responded with status code %d that matched "%s" in %dms' % (status, status_regex, rtt)
                else:
                    event = 'HttpResponseRegexError'
                    severity = 'major'
                    value = '%s (%d)' % (description, status)
                    text = 'HTTP server responded with status code %d that failed to match "%s"' % (status, status_regex)

            elif 100 <= status <= 199:
                event = 'HttpInformational'
                severity = 'normal'
                value = '%s (%d)' % (description, status)
                text = 'HTTP server responded with status code %d in %dms' % (status, rtt)

            elif 200 <= status <= 299:
                event = 'HttpResponseOK'
                severity = 'normal'
                value = '%s (%d)' % (description, status)
                text = 'HTTP server responded with status code %d in %dms' % (status, rtt)

            elif 300 <= status <= 399:
                event = 'HttpRedirection'
                severity = 'minor'
                value = '%s (%d)' % (description, status)
                text = 'HTTP server responded with status code %d in %dms' % (status, rtt)

            elif 400 <= status <= 499:
                event = 'HttpClientError'
                severity = 'minor'
                value = '%s (%d)' % (description, status)
                text = 'HTTP server responded with status code %d in %dms' % (status, rtt)

            elif 500 <= status <= 599:
                event = 'HttpServerError'
                severity = 'major'
                value = '%s (%d)' % (description, status)
                text = 'HTTP server responded with status code %d in %dms' % (status, rtt)

            else:
                event = 'HttpUnknownError'
                severity = 'warning'
                value = 'UNKNOWN'
                text = 'HTTP request resulted in an unhandled error.'

            if event in ['HttpResponseOK', 'HttpResponseRegexOK']:
                if rtt > crit_thold:
                    event = 'HttpResponseSlow'
                    severity = 'critical'
                    value = '%dms' % rtt
                    text = 'Website available but exceeding critical RT thresholds of %dms' % crit_thold
                elif rtt > warn_thold:
                    event = 'HttpResponseSlow'
                    severity = 'warning'
                    value = '%dms' % rtt
                    text = 'Website available but exceeding warning RT thresholds of %dms' % warn_thold
                if search_string and body:
                    LOG.debug('Searching for %s', search_string)
                    found = False
                    for line in body.split('\n'):
                        m = re.search(search_string, line)
                        if m:
                            found = True
                            LOG.debug("Regex: Found %s in %s", search_string, line)
                            break
                    if not found:
                        event = 'HttpContentError'
                        severity = 'minor'
                        value = 'Search failed'
                        text = 'Website available but pattern "%s" not found' % search_string
                elif rule and body:
                    LOG.debug('Evaluating rule %s', rule)
                    headers = check.get('headers', {})
                    if 'Content-type' in headers and headers['Content-type'] == 'application/json':
                        try:
                            body = json.loads(body)
                        except ValueError as e:
                            LOG.error('Could not evaluate rule %s: %s', rule, e)
                    try:
                        eval(rule)  # NOTE: assumes request body in variable called 'body'
                    except (SyntaxError, NameError, ZeroDivisionError) as e:
                        LOG.error('Could not evaluate rule %s: %s', rule, e)
                    except Exception as e:
                        LOG.error('Could not evaluate rule %s: %s', rule, e)
                    else:
                        if not eval(rule):
                            event = 'HttpContentError'
                            severity = 'minor'
                            value = 'Rule failed'
                            text = 'Website available but rule evaluation failed (%s)' % rule

            LOG.debug("URL: %s, Status: %s (%s), Round-Trip Time: %dms -> %s",
                      check['url'], description, status, rtt, event)

            resource = check['resource']
            correlate = _HTTP_ALERTS
            group = 'Web'
            environment = check['environment']
            service = check['service']
            text = text
            tags = check.get('tags', list())
            threshold_info = "%s : RT > %d RT > %d x %s" % (check['url'], warn_thold, crit_thold, check.get('count', 1))

            try:
                local_api.send_alert(
                    resource=resource,
                    event=event,
                    correlate=correlate,
                    group=group,
                    value=value,
                    severity=severity,
                    environment=environment,
                    service=service,
                    text=text,
                    event_type='serviceAlert',
                    tags=tags,
                    attributes={
                        'thresholdInfo': threshold_info
                    }
                )
            except Exception as e:
                LOG.warning('Failed to send alert: %s', e)

            if check_ssl:
                ssl_date_fmt = r'%b %d %H:%M:%S %Y %Z'
                context = ssl.create_default_context()
                domain = '{uri.netloc}'.format(uri=urllib.parse.urlparse(check.get('url')))
                port = urllib.parse.urlparse(check.get('url')).port or 443
                conn = context.wrap_socket(
                    socket.socket(socket.AF_INET),
                    server_hostname=domain
                )
                conn.settimeout(3.0)
                conn.connect((domain, port))
                ssl_info = conn.getpeercert()
                days_left = datetime.datetime.strptime(ssl_info['notAfter'], ssl_date_fmt) - datetime.datetime.utcnow()
                if days_left < datetime.timedelta(days=0):
                    text = 'HTTPS cert for %s expired' % check['resource']
                    severity = 'critical'
                elif days_left < datetime.timedelta(days=SSL_DAYS) and days_left > datetime.timedelta(days=SSL_DAYS_PANIC):
                    text = 'HTTPS cert for %s will expire at %s' % (check['resource'], days_left)
                    severity = 'major'
                elif days_left <= datetime.timedelta(days=SSL_DAYS_PANIC):
                    text = 'HTTPS cert for %s will expire at %s' % (check['resource'], days_left)
                    severity = 'critical'
                else:
                    severity = 'normal'

                try:
                    local_api.send_alert(
                        resource=resource,
                        event='HttpSSLChecker',
                        correlate=correlate,
                        group=group,
                        value='0',
                        severity=severity,
                        environment=environment,
                        service=service,
                        text=text,
                        event_type='serviceAlert',
                        tags=tags,
                        attributes={
                            'thresholdInfo': threshold_info
                        }
                    )
                except Exception as e:
                    LOG.warning('Failed to send ssl alert: %s', e)

            self.queue.task_done()
            LOG.info('%s check complete.', self.getName())

        self.queue.task_done()
Exemple #48
0
class FormatsTestCase(unittest.TestCase):

    def setUp(self):
        self.client = Client()

        self.alert = """
            {
                "alert": {
                  "attributes": {
                    "ip": "127.0.0.1"
                  },
                  "correlate": [],
                  "createTime": "2018-04-08T19:01:44.979Z",
                  "customer": null,
                  "duplicateCount": 0,
                  "environment": "Development",
                  "event": "foo",
                  "group": "Misc",
                  "history": [
                    {
                      "event": "foo",
                      "href": "https://alerta-api.herokuapp.com/alert/d1bb37cf-e976-429e-96f5-82b2a48aa50b",
                      "id": "d1bb37cf-e976-429e-96f5-82b2a48aa50b",
                      "severity": null,
                      "status": "shelved",
                      "text": "shelved by Test90",
                      "type": "status",
                      "updateTime": "2018-04-09T09:11:43.502Z",
                      "value": null
                    },
                    {
                      "event": "foo",
                      "href": "https://alerta-api.herokuapp.com/alert/d1bb37cf-e976-429e-96f5-82b2a48aa50b",
                      "id": "d1bb37cf-e976-429e-96f5-82b2a48aa50b",
                      "severity": null,
                      "status": "open",
                      "text": "bulk status change via console by test",
                      "type": "status",
                      "updateTime": "2018-04-24T17:52:40.088Z",
                      "value": null
                    },
                    {
                      "event": "foo",
                      "href": "https://alerta-api.herokuapp.com/alert/d1bb37cf-e976-429e-96f5-82b2a48aa50b",
                      "id": "d1bb37cf-e976-429e-96f5-82b2a48aa50b",
                      "severity": "minor",
                      "status": "shelved",
                      "text": "status change via console by Scott Wenzel",
                      "type": "action",
                      "updateTime": "2018-05-18T03:38:50.333Z",
                      "value": null
                    }
                  ],
                  "href": "https://alerta-api.herokuapp.com/alert/d1bb37cf-e976-429e-96f5-82b2a48aa50b",
                  "id": "d1bb37cf-e976-429e-96f5-82b2a48aa50b",
                  "lastReceiveId": "d1bb37cf-e976-429e-96f5-82b2a48aa50b",
                  "lastReceiveTime": "2018-04-08T19:01:46.090Z",
                  "origin": "alertad/fdaa33ca.lan",
                  "previousSeverity": "indeterminate",
                  "rawData": null,
                  "receiveTime": "2018-04-08T19:01:46.090Z",
                  "repeat": false,
                  "resource": "quux",
                  "service": [
                    "Bar"
                  ],
                  "severity": "minor",
                  "status": "shelved",
                  "tags": [
                    "watch:Scott Wenzel"
                  ],
                  "text": "",
                  "timeout": 3600,
                  "trendIndication": "moreSevere",
                  "type": "exceptionAlert",
                  "value": null
                }
            }
        """

    @requests_mock.mock()
    def test_alert(self, m):
        m.post('http://localhost:8080/alert', text=self.alert)
        msg = {'event': 'foo', 'service': ['Bar']}

        id, alert, message = self.client.send_alert(
            environment='Production',
            resource='quux',
            **msg
        )
        alert_summary = alert.tabular(fields='summary', timezone='UTC')
        self.assertEqual(alert_summary['id'], 'd1bb37cf')

        alert_summary = alert.tabular(fields='details', timezone='UTC')
        self.assertEqual(alert_summary['severity'], 'indeterminate -> minor')

        alert_summary = alert.tabular(fields='all', timezone='UTC')
        self.assertEqual(alert_summary['history'][0]['status'], 'shelved')
Exemple #49
0
    def setUp(self):
        self.client = Client()

        self.user = """
Exemple #50
0
    def setUp(self):
        self.client = Client()

        self.alert = """
Exemple #51
0
    def test_action(self, trapper, endpoint, key=None):

        hosts = self.zapi.host.get()
        zabbix_server_id = [h for h in hosts if h['name'] == 'Zabbix server'][0]['hostid']

        # enable zabbix server monitoring
        self.zapi.host.update(hostid=zabbix_server_id, status=ENABLED)

        description = 'Test trigger event on {HOST.NAME}'
        try:
            response = self.zapi.item.create(
                name='Test Zabbix-Alerta Integration',
                type=ZABBIX_TRAPPER,
                key_='test.alerta',
                value_type=TEXT,
                hostid=zabbix_server_id,
                status=ENABLED
            )
            self.item_id = response['itemids'][0]

            response = self.zapi.trigger.create(
                hostid=zabbix_server_id,
                description=description,
                expression='{Zabbix server:test.alerta.diff()}>0',
                type=GENERATE_MULTIPLE_EVENTS,
                priority=INFORMATION,
                status=ENABLED,
                manual_close=ALLOW_MANUAL_CLOSE
            )
            self.trigger_id = response['triggerids'][0]
        except ZabbixAPIException:
            triggers = self.zapi.trigger.get(hostids=zabbix_server_id)
            self.trigger_id = [t for t in triggers if t['description'] == description][0]['triggerid']
            self.item_id = self.zapi.item.get(triggerids=self.trigger_id)[0]['itemid']

        def zabbix_send(value):
            cfg = protobix.ZabbixAgentConfig()
            cfg.server_active = trapper
            zbx = protobix.DataContainer(cfg)

            zbx.data_type = 'items'
            zbx.add_item(host='Zabbix server', key='test.alerta', value=value)
            response = zbx.send()
            print(response)

        print('sending test items')
        now = int(time.time())
        zabbix_send('OK')

        print('wait for items to be received')
        count = 0
        while True:
            count += 1
            response = self.zapi.history.get(itemids=[self.item_id], history=TEXT, time_from=now, output='extend', sortfield='clock',
                                             sortorder='DESC', limit=10)
            zabbix_send('RETRY%s' % count)
            if len(response) > 1:
                break
            print('waiting 5 seconds...')
            time.sleep(5)

        print('sent items received by zabbix')
        print(response)

        from_date = datetime.utcnow().replace(microsecond=0).isoformat() + ".000Z"

        print('wait for triggered event')
        while True:
            response = self.zapi.event.get(objectids=self.trigger_id, time_from=now, output='extend',
                                           sortfield=['clock', 'eventid'], sortorder='DESC')
            if len(response) > 0 and 'eventid' in response[0]:
                event_id = response[0]['eventid']
                break
            print('waiting 2 seconds...')
            time.sleep(2)

        print('event triggered')
        print(response[0])

        print('wait for alert')
        while True:
            response = self.zapi.alert.get(eventid=event_id, time_from=now, output='extend',)
            if len(response) > 0:
                break
            print('waiting 2 seconds...')
            time.sleep(2)

        print('alert triggered by event')
        print(response[0])

        api = Client(endpoint, key)

        print('check alert received by Alerta')
        while True:
            try:
                response = api.get_alerts(query=[('event', 'test.alerta'), ('from-date', from_date)])
            except Exception as e:
                sys.exit(e)
            if len(response) > 0:
                break
            time.sleep(5)
        print(response[0].last_receive_id)

        print('success!')
Exemple #52
0
def main():

    config_file = os.environ.get('ALERTA_CONF_FILE') or OPTIONS['config_file']

    config = configparser.RawConfigParser(defaults=OPTIONS)
    try:
        config.read(os.path.expanduser(config_file))
    except Exception:
        sys.exit("Problem reading configuration file %s - is this an ini file?" % config_file)

    parser = argparse.ArgumentParser(
        prog='zabbix-alerta',
        usage='zabbix-alerta SENDTO SUMMARY BODY',
        description='Zabbix-to-Alerta integration script',
        epilog=epilog,
        formatter_class=argparse.RawTextHelpFormatter
    )
    parser.add_argument(
        'sendto',
        help='config profile or alerta API endpoint and key'
    )
    parser.add_argument(
        'summary',
        help='alert summary'
    )
    parser.add_argument(
        'body',
        help='alert body (see format below)'
    )
    args, left = parser.parse_known_args()

    # sendto=apiUrl[;key]
    if args.sendto.startswith('http://') or args.sendto.startswith('https://'):
        want_profile = None
        try:
            OPTIONS['endpoint'], OPTIONS['key'] = args.sendto.split(';', 1)
        except ValueError:
            OPTIONS['endpoint'] = args.sendto
    # sendto=profile
    else:
        want_profile = args.sendto or os.environ.get('ALERTA_DEFAULT_PROFILE') or config.defaults().get('profile')

        if want_profile and config.has_section('profile %s' % want_profile):
            for opt in OPTIONS:
                try:
                    OPTIONS[opt] = config.getboolean('profile %s' % want_profile, opt)
                except (ValueError, AttributeError):
                    OPTIONS[opt] = config.get('profile %s' % want_profile, opt)
        else:
            for opt in OPTIONS:
                try:
                    OPTIONS[opt] = config.getboolean('DEFAULT', opt)
                except (ValueError, AttributeError):
                    OPTIONS[opt] = config.get('DEFAULT', opt)

    parser.set_defaults(**OPTIONS)
    args = parser.parse_args()

    if args.debug or not os.path.isdir('/var/log/zabbix'):
        LOG.basicConfig(stream=sys.stderr, format=LOG_FORMAT, datefmt=LOG_DATE_FMT, level=LOG.DEBUG)
    else:
        LOG.basicConfig(filename=LOG_FILE, format=LOG_FORMAT, datefmt=LOG_DATE_FMT, level=LOG.INFO)

    LOG.info("[alerta] endpoint=%s key=%s", args.endpoint, args.key)
    api = Client(endpoint=args.endpoint, key=args.key, ssl_verify=args.sslverify)

    LOG.debug("[alerta] sendto=%s, summary=%s, body=%s", args.sendto, args.summary, args.body)
    try:
        alert = parse_zabbix(args.summary, args.body)
        api.send_alert(**alert)
    except (SystemExit, KeyboardInterrupt):
        LOG.warning("Exiting zabbix-alerta.")
        sys.exit(0)
    except Exception as e:
        LOG.error(e, exc_info=1)
        sys.exit(1)
Exemple #53
0
class SnmpTrapHandler(object):

    def __init__(self):

        self.api = None

    def run(self):

        endpoint = os.environ.get('ALERTA_ENDPOINT', 'http://localhost:8080')
        key = os.environ.get('ALERTA_API_KEY', None)

        self.api = Client(endpoint=endpoint, key=key)

        data = sys.stdin.read()
        LOG.info('snmptrapd -> %r', data)
        try:
            data = unicode(data, 'utf-8', errors='ignore')  # python 2
        except NameError:
            pass
        LOG.debug('unicoded -> %s', data)

        try:
            resource, event, correlate, trap_version, trapvars = self.parse_snmptrap(data)
            if resource and event:
                self.api.send_alert(
                    resource=resource,
                    event=event,
                    correlate=correlate,
                    group='SNMP',
                    value=trapvars['$w'],
                    severity='indeterminate',
                    environment='Production',
                    service=['Network'],
                    text=trapvars['$W'],
                    event_type='snmptrapAlert',
                    attributes={'trapvars': {k.replace('$', '_'): v for k, v in trapvars.items()}},
                    tags=[trap_version],
                    create_time=datetime.datetime.strptime('%sT%s.000Z' % (trapvars['$x'], trapvars['$X']), '%Y-%m-%dT%H:%M:%S.%fZ'),
                    raw_data=data
                )
        except Exception as e:
            LOG.warning('Failed to send alert: %s', e)

        LOG.debug('Send heartbeat...')
        try:
            origin = '{}/{}'.format('snmptrap', platform.uname()[1])
            self.api.heartbeat(origin, tags=[__version__])
        except Exception as e:
            LOG.warning('Failed to send heartbeat: %s', e)

    def parse_snmptrap(self, data):

        pdu_data = data.splitlines()
        varbind_list = pdu_data[:]

        trapvars = dict()
        for line in pdu_data:
            if line.startswith('$'):
                special, value = line.split(None, 1)
                trapvars[special] = value
                varbind_list.pop(0)

        if '$s' in trapvars:
            if trapvars['$s'] == '0':
                trap_version = 'SNMPv1'
            elif trapvars['$s'] == '1':
                trap_version = 'SNMPv2c'
            elif trapvars['$s'] == '2':
                trap_version = 'SNMPv2u'  # not supported
            else:
                trap_version = 'SNMPv3'
            trapvars['$s'] = trap_version
        else:
            LOG.warning('Failed to parse unknown trap type.')
            return

        # Get varbinds
        varbinds = dict()
        idx = 0
        for varbind in '\n'.join(varbind_list).split('~%~'):
            if varbind == '':
                break
            idx += 1
            try:
                oid, value = varbind.split(None, 1)
            except ValueError:
                oid = varbind
                value = ''
            varbinds[oid] = value
            trapvars['$' + str(idx)] = value  # $n
            LOG.debug('$%s %s', str(idx), value)

        trapvars['$q'] = trapvars['$q'].lstrip('.')  # if numeric, remove leading '.'
        trapvars['$#'] = str(idx)

        LOG.debug('varbinds = %s', varbinds)

        correlate = list()
        if trap_version == 'SNMPv1':
            if trapvars['$w'] == '0':
                trapvars['$O'] = 'coldStart'
                correlate = ['coldStart', 'warmStart']
            elif trapvars['$w'] == '1':
                trapvars['$O'] = 'warmStart'
                correlate = ['coldStart', 'warmStart']
            elif trapvars['$w'] == '2':
                trapvars['$O'] = 'linkDown'
                correlate = ['linkUp', 'linkDown']
            elif trapvars['$w'] == '3':
                trapvars['$O'] = 'linkUp'
                correlate = ['linkUp', 'linkDown']
            elif trapvars['$w'] == '4':
                trapvars['$O'] = 'authenticationFailure'
            elif trapvars['$w'] == '5':
                trapvars['$O'] = 'egpNeighborLoss'
            elif trapvars['$w'] == '6':  # enterpriseSpecific(6)
                if trapvars['$q'].isdigit():  # XXX - specific trap number was not decoded
                    trapvars['$O'] = '%s.0.%s' % (trapvars['$N'], trapvars['$q'])
                else:
                    trapvars['$O'] = trapvars['$q']

        elif trap_version == 'SNMPv2c':
            if 'coldStart' in trapvars['$2']:
                trapvars['$w'] = '0'
                trapvars['$W'] = 'Cold Start'
            elif 'warmStart' in trapvars['$2']:
                trapvars['$w'] = '1'
                trapvars['$W'] = 'Warm Start'
            elif 'linkDown' in trapvars['$2']:
                trapvars['$w'] = '2'
                trapvars['$W'] = 'Link Down'
            elif 'linkUp' in trapvars['$2']:
                trapvars['$w'] = '3'
                trapvars['$W'] = 'Link Up'
            elif 'authenticationFailure' in trapvars['$2']:
                trapvars['$w'] = '4'
                trapvars['$W'] = 'Authentication Failure'
            elif 'egpNeighborLoss' in trapvars['$2']:
                trapvars['$w'] = '5'
                trapvars['$W'] = 'EGP Neighbor Loss'
            else:
                trapvars['$w'] = '6'
                trapvars['$W'] = 'Enterprise Specific'
            trapvars['$O'] = trapvars['$2']  # SNMPv2-MIB::snmpTrapOID.0
        LOG.debug('trapvars = %s', trapvars)

        LOG.info('%s-Trap-PDU %s from %s at %s %s', trap_version, trapvars['$O'], trapvars['$B'], trapvars['$x'], trapvars['$X'])

        if trapvars['$B'] != '<UNKNOWN>':
            resource = trapvars['$B']
        elif trapvars['$A'] != '0.0.0.0':
            resource = trapvars['$A']
        else:
            m = re.match(r'UDP: \[(\d+\.\d+\.\d+\.\d+)\]', trapvars['$b'])
            if m:
                resource = m.group(1)
            else:
                resource = '<NONE>'

        return resource, trapvars['$O'], correlate, trap_version, trapvars
Exemple #54
0
class AlertTestCase(unittest.TestCase):

    def setUp(self):
        self.client = Client()

        self.alert = """
            {
              "alert": {
                "attributes": {
                  "ip": "127.0.0.1",
                  "notify": false
                },
                "correlate": [],
                "createTime": "2017-10-03T09:12:27.283Z",
                "customer": null,
                "duplicateCount": 4,
                "environment": "Production",
                "event": "node_down",
                "group": "Misc",
                "history": [],
                "href": "http://localhost:8080/alert/e7020428-5dad-4a41-9bfe-78e9d55cda06",
                "id": "e7020428-5dad-4a41-9bfe-78e9d55cda06",
                "lastReceiveId": "534ced13-ddb0-435e-8f94-a38691719683",
                "lastReceiveTime": "2017-10-03T09:15:06.156Z",
                "origin": "alertad/fdaa33ca.local",
                "previousSeverity": "indeterminate",
                "rawData": null,
                "receiveTime": "2017-10-03T09:12:27.289Z",
                "repeat": true,
                "resource": "web01",
                "service": [
                  "Web",
                  "App"
                ],
                "severity": "critical",
                "status": "open",
                "tags": [
                  "london",
                  "linux"
                ],
                "text": "",
                "timeout": 86400,
                "trendIndication": "moreSevere",
                "type": "exceptionAlert",
                "value": "4"
              },
              "id": "e7020428-5dad-4a41-9bfe-78e9d55cda06",
              "status": "ok"
            }
        """

    @requests_mock.mock()
    def test_alert(self, m):
        m.post('http://localhost:8080/alert', text=self.alert)
        id, alert, message = self.client.send_alert(
            environment='Production', resource='web01', event='node_down', correlated=['node_up', 'node_down'],
            service=['Web', 'App'], severity='critical', tags=['london', 'linux'], value=4
        )
        self.assertEqual(alert.value, '4')  # values cast to string
        self.assertEqual(alert.timeout, 86400)  # timeout returned as int
        self.assertIn('london', alert.tags)