Beispiel #1
0
    def test_parse_logline_syslog(self):
        """Tests if the parse_logline() function parses syslog correctly. """
        line = ("Feb 22 10:17:10 host malware-domain-list-collector: ERROR "
                "Something went wrong")
        thread = (
            "Feb 22 10:17:10 host malware-domain-list-collector.4: ERROR "
            "Something went wrong")

        actual = utils.parse_logline(line, regex=utils.SYSLOG_REGEX)
        self.assertEqual(
            {
                'bot_id': 'malware-domain-list-collector',
                'date': '%d-02-22T10:17:10' % datetime.datetime.now().year,
                'thread_id': None,
                'log_level': 'ERROR',
                'message': 'Something went wrong'
            }, actual)
        actual = utils.parse_logline(thread, regex=utils.SYSLOG_REGEX)
        self.assertEqual(
            {
                'bot_id': 'malware-domain-list-collector',
                'date': '%d-02-22T10:17:10' % datetime.datetime.now().year,
                'thread_id': 4,
                'log_level': 'ERROR',
                'message': 'Something went wrong'
            }, actual)
Beispiel #2
0
    def test_parse_logline(self):
        """Tests if the parse_logline() function works as expected"""
        line = ("2015-05-29 21:00:24,379 - malware-domain-list-collector - "
                "ERROR - Something went wrong")
        thread = (
            "2015-05-29 21:00:24,379 - malware-domain-list-collector.4 - "
            "ERROR - Something went wrong")

        fields = utils.parse_logline(line)
        self.assertDictEqual(
            {
                'date': '2015-05-29T21:00:24.379000',
                'bot_id': 'malware-domain-list-collector',
                'thread_id': None,
                'log_level': 'ERROR',
                'message': 'Something went wrong'
            }, fields)
        fields = utils.parse_logline(thread)
        self.assertDictEqual(
            {
                'date': '2015-05-29T21:00:24.379000',
                'bot_id': 'malware-domain-list-collector',
                'thread_id': 4,
                'log_level': 'ERROR',
                'message': 'Something went wrong'
            }, fields)
Beispiel #3
0
    def read_bot_log(self, bot_id, log_level, number_of_lines):
        if self.parameters.logging_handler == 'file':
            bot_log_path = os.path.join(self.parameters.logging_path,
                                        bot_id + '.log')
            if not os.path.isfile(bot_log_path):
                logger.error("Log path not found: {}".format(bot_log_path))
                return []
        elif self.parameters.logging_handler == 'syslog':
            bot_log_path = '/var/log/syslog'

        if not os.access(bot_log_path, os.R_OK):
            self.logger.error('File %r is not readable.' % bot_log_path)
            return 'error'

        messages = list()

        message_overflow = ''
        message_count = 0

        for line in utils.reverse_readline(bot_log_path):
            if self.parameters.logging_handler == 'file':
                log_message = utils.parse_logline(line)
            if self.parameters.logging_handler == 'syslog':
                log_message = utils.parse_logline(line,
                                                  regex=utils.SYSLOG_REGEX)

            if type(log_message) is not dict:
                if self.parameters.logging_handler == 'file':
                    message_overflow = '\n'.join([line, message_overflow])
                continue
            if log_message['bot_id'] != bot_id:
                continue
            if LOG_LEVEL[log_message['log_level']] < LOG_LEVEL[log_level]:
                continue

            if message_overflow:
                log_message['extended_message'] = message_overflow
                message_overflow = ''

            if self.parameters.logging_handler == 'syslog':
                log_message['message'] = log_message['message'].replace(
                    '#012', '\n')

            message_count += 1
            messages.append(log_message)

            if message_count >= number_of_lines and number_of_lines != -1:
                break

        log_log_messages(messages[::-1])
        return messages[::-1]
Beispiel #4
0
    def read_bot_log(self, bot_id, log_level, number_of_lines):
        if self.parameters.logging_handler == 'file':
            bot_log_path = os.path.join(self.parameters.logging_path,
                                        bot_id + '.log')
            if not os.path.isfile(bot_log_path):
                logger.error("Log path not found: %s", bot_log_path)
                return 2, []
        elif self.parameters.logging_handler == 'syslog':
            bot_log_path = '/var/log/syslog'
        else:
            self.abort("Unknow logging handler %r" % self.parameters.logging_handler)

        if not os.access(bot_log_path, os.R_OK):
            self.logger.error('File %r is not readable.', bot_log_path)
            return 1, 'error'

        messages = []

        message_overflow = ''
        message_count = 0

        for line in utils.reverse_readline(bot_log_path):
            if self.parameters.logging_handler == 'file':
                log_message = utils.parse_logline(line)
            if self.parameters.logging_handler == 'syslog':
                log_message = utils.parse_logline(line, regex=utils.SYSLOG_REGEX)

            if type(log_message) is not dict:
                if self.parameters.logging_handler == 'file':
                    message_overflow = '\n'.join([line, message_overflow])
                continue
            if log_message['bot_id'] != bot_id:
                continue
            if LOG_LEVEL[log_message['log_level']] < LOG_LEVEL[log_level]:
                continue

            if message_overflow:
                log_message['extended_message'] = message_overflow
                message_overflow = ''

            if self.parameters.logging_handler == 'syslog':
                log_message['message'] = log_message['message'].replace('#012', '\n')

            message_count += 1
            messages.append(log_message)

            if message_count >= number_of_lines and number_of_lines != -1:
                break

        log_log_messages(messages[::-1])
        return 0, messages[::-1]
Beispiel #5
0
    def test_logs(self):
        """ Test if bot log messages are correctly formatted. """
        self.run_bot()
        self.assertLoglineMatches(
            0, "{} initialized with id {} and version"
            " [0-9.]{{5}} \([a-zA-Z0-9,:. ]+\)( \[GCC\])?"
            " as process [0-9]+\."
            "".format(self.bot_name, self.bot_id), "INFO")
        self.assertRegexpMatchesLog("INFO - Bot is starting.")
        self.assertLoglineEqual(-1, "Bot stopped.", "INFO")
        for logline in self.loglines:
            fields = utils.parse_logline(logline)
            self.assertTrue(fields['message'][-1] in '.?!',
                            msg='Logline {!r} does not end with .? or !.'
                            ''.format(fields['message']))
            self.assertTrue(
                fields['message'].upper() == fields['message'].upper(),
                msg='Logline {!r} does not beginn with an upper case char.'
                ''.format(fields['message']))
        self.assertNotRegexpMatchesLog("(ERROR.*?){}"
                                       "".format(self.allowed_error_count))
        self.assertNotRegexpMatchesLog("CRITICAL")

        #        """ Test if all pipes are created with correct names. """
        pipenames = ["{}-input", "{}-input-internal", "{}-output"]
        self.assertSetEqual({x.format(self.bot_id)
                             for x in pipenames}, set(self.pipe.state.keys()))
Beispiel #6
0
    def read_bot_log(self, bot_id, log_level, number_of_lines):
        bot_log_path = os.path.join(self.parameters.logging_path,
                                    bot_id + '.log')
        if not os.path.isfile(bot_log_path):
            logger.error("Log path not found: {}".format(bot_log_path))
            return []

        messages = list()

        message_overflow = ''
        message_count = 0

        for line in utils.reverse_readline(bot_log_path):
            log_message = utils.parse_logline(line)

            if type(log_message) is not dict:
                message_overflow = '\n'.join([line, message_overflow])
                continue
            if LOG_LEVEL[log_message['log_level']] < log_level:
                continue

            if message_overflow:
                log_message['extended_message'] = message_overflow
                message_overflow = ''

            message_count += 1
            messages.append(log_message)

            if message_count >= number_of_lines and number_of_lines != -1:
                break

        log_log_messages(messages[::-1])
        return messages[::-1]
Beispiel #7
0
    def run_bot(self, iterations: int = 1, error_on_pipeline: bool = False):
        """
        Call this method for actually doing a test run for the specified bot.

        Parameters:
            iterations: Bot instance will be run the given times, defaults to 1.
        """
        self.prepare_bot()
        with mock.patch('intelmq.lib.utils.load_configuration',
                        new=self.mocked_config):
            with mock.patch('intelmq.lib.utils.log', self.mocked_log):
                for run in range(iterations):
                    self.bot.start(error_on_pipeline=error_on_pipeline,
                                   source_pipeline=self.pipe,
                                   destination_pipeline=self.pipe)
        self.loglines_buffer = self.log_stream.getvalue()
        self.loglines = self.loglines_buffer.splitlines()
        """ Test if all pipes are created with correct names. """
        pipenames = ["{}-input", "{}-input-internal", "{}-output"]
        self.assertSetEqual({x.format(self.bot_id)
                             for x in pipenames}, set(self.pipe.state.keys()))
        """ Test if report has required fields. """
        if self.bot_type == 'collector':
            for report_json in self.get_output_queue():
                report = message.MessageFactory.unserialize(
                    report_json, harmonization=self.harmonization)
                self.assertIsInstance(report, message.Report)
                self.assertIn('feed.name', report)
                self.assertIn('raw', report)
                self.assertIn('time.observation', report)
        """ Test if event has required fields. """
        if self.bot_type == 'parser':
            for event_json in self.get_output_queue():
                event = message.MessageFactory.unserialize(
                    event_json, harmonization=self.harmonization)
                self.assertIsInstance(event, message.Event)
                self.assertIn('classification.type', event)
                self.assertIn('raw', event)
        """ Test if bot log messages are correctly formatted. """
        self.assertLoglineMatches(
            0, "{} initialized with id {} and version"
            " [0-9.]{{5}} \([a-zA-Z0-9,:. ]+\)( \[GCC\])?"
            " as process [0-9]+\."
            "".format(self.bot_name, self.bot_id), "INFO")
        self.assertRegexpMatchesLog("INFO - Bot is starting.")
        self.assertLoglineEqual(-1, "Bot stopped.", "INFO")
        self.assertNotRegexpMatchesLog("(ERROR.*?){%d}" %
                                       (self.allowed_error_count + 1))
        self.assertNotRegexpMatchesLog("CRITICAL")
        """ If no error happened (incl. tracebacks, we can check for formatting) """
        if not self.allowed_error_count:  # This would fail for tracebacks currently
            for logline in self.loglines:
                fields = utils.parse_logline(logline)
                self.assertTrue(fields['message'][-1] in '.:?!',
                                msg='Logline {!r} does not end with .? or !.'
                                ''.format(fields['message']))
                self.assertTrue(
                    fields['message'].upper() == fields['message'].upper(),
                    msg='Logline {!r} does not begin with an upper case char.'
                    ''.format(fields['message']))
Beispiel #8
0
    def test_logs(self):
#        """ Test if bot logs initialized message. """
        self.run_bot()
        self.assertLoglineMatches(0, "{} initialized with id {} and version"
                                     " [0-9.]{{5}} \([a-zA-Z0-9,:. ]+\)( \[GCC\])?"
                                     " as process [0-9]+\."
                                     "".format(self.bot_name,
                                               self.bot_id), "INFO")
        self.assertRegexpMatchesLog("INFO - Bot is starting.")
        self.assertLoglineEqual(-1, "Bot stopped.", "INFO")
        for logline in self.loglines:
            fields = utils.parse_logline(logline)
            self.assertTrue(fields['message'][-1] in '.?!',
                            msg='Logline {!r} does not end with .? or !.'
                                ''.format(fields['message']))
            self.assertTrue(fields['message'].upper() == fields['message'].upper(),
                            msg='Logline {!r} does not beginn with an upper case char.'
                                ''.format(fields['message']))
        self.assertNotRegexpMatchesLog("(ERROR.*?){}"
                                       "".format(self.allowed_error_count))
        self.assertNotRegexpMatchesLog("CRITICAL")

#        """ Test if all pipes are created with correct names. """
        pipenames = ["{}-input", "{}-input-internal", "{}-output"]
        self.assertSetEqual({x.format(self.bot_id) for x in pipenames},
                            set(self.pipe.state.keys()))
Beispiel #9
0
 def test_log_end_dot(self):
     """ Test if every log lines ends with a dot. """
     for logline in self.loglines:
         fields = utils.parse_logline(logline)
         self.assertTrue(fields['message'].endswith('.'),
                         msg='Logline {} does not end with dot.'
                             ''.format(fields['message']))
Beispiel #10
0
    def read_bot_log(self, bot_id, log_level, number_of_lines):
        bot_log_path = os.path.join(self.system['logging_path'],
                                    bot_id + '.log')
        if not os.path.isfile(bot_log_path):
            logger.error("Log path not found: {}".format(bot_log_path))
            return []

        messages = list()

        message_overflow = ''
        message_count = 0

        for line in utils.reverse_readline(bot_log_path):
            log_message = utils.parse_logline(line)

            if type(log_message) is not dict:
                message_overflow = '\n'.join([line, message_overflow])
                continue
            if LOG_LEVEL[log_message['log_level']] < log_level:
                continue

            if message_overflow:
                log_message['extended_message'] = message_overflow
                message_overflow = ''

            message_count += 1
            messages.append(log_message)

            if message_count >= number_of_lines and number_of_lines != -1:
                break

        log_log_messages(messages[::-1])
        return messages[::-1]
Beispiel #11
0
 def test_log_end_dot(self):
     """ Test if every log lines ends with a dot. """
     for logline in self.loglines:
         fields = utils.parse_logline(logline)
         self.assertTrue(fields['message'].endswith('.'),
                         msg='Logline {} does not end with dot.'
                         ''.format(fields['message']))
Beispiel #12
0
    def assertLoglineEqual(self,
                           line_no: int,
                           message: str,
                           levelname: str = "ERROR"):
        """
        Asserts if a logline matches a specific requirement.

        Parameters:
            line_no: Number of the logline which is asserted
            message: Message text which is compared
            levelname: Log level of logline which is asserted
        """
        if sys.version_info >= (3, 7):
            return True

        self.assertIsNotNone(self.loglines)
        logline = self.loglines[line_no]
        fields = utils.parse_logline(logline)

        self.assertEqual(
            self.bot_id, fields["bot_id"], "bot_id %s didn't match %s"
            "".format(self.bot_id, fields["bot_id"]))

        self.assertEqual(levelname, fields["log_level"])
        self.assertEqual(message, fields["message"])
Beispiel #13
0
    def test_parse_logline_invalid(self):
        """Tests if the parse_logline() function returns the line. """
        line = ("    report = self.receive_message()\n  File"
                " \"/usr/local/lib/python3.4/dist-packages/intelmq-1.0.0"
                "-py3.4.egg/intelmq/lib/bot.py\", line 259, in"
                " receive_message")

        actual = utils.parse_logline(line)
        self.assertEqual(line, actual)
Beispiel #14
0
    def test_parse_logline_invalid(self):
        """Tests if the parse_logline() function returns the line. """
        line = ("    report = self.receive_message()\n  File"
                " \"/usr/local/lib/python3.4/dist-packages/intelmq-1.0.0"
                "-py3.4.egg/intelmq/lib/bot.py\", line 259, in"
                " receive_message")

        actual = utils.parse_logline(line)
        self.assertEqual(line, actual)
Beispiel #15
0
    def run_bot(self, iterations=1):
        """
        Call this method for actually doing a test run for the specified bot.

        Parameters
        ----------
        iterations : integer
            Bot instance will be run the given times, defaults to 1.
        """
        self.prepare_bot()
        with mock.patch('intelmq.lib.utils.load_configuration',
                        new=self.mocked_config):
            with mock.patch('intelmq.lib.utils.log', self.mocked_log):
                for run in range(iterations):
                    self.bot.start(error_on_pipeline=False,
                                   source_pipeline=self.pipe,
                                   destination_pipeline=self.pipe)
        self.loglines_buffer = self.log_stream.getvalue()
        self.loglines = self.loglines_buffer.splitlines()

        """ Test if report has required fields. """
        if self.bot_type == 'collector':
            for report_json in self.get_output_queue():
                report = message.MessageFactory.unserialize(report_json)
                self.assertIsInstance(report, message.Report)
                self.assertIn('feed.name', report)
                self.assertIn('raw', report)
                self.assertIn('time.observation', report)

        """ Test if event has required fields. """
        if self.bot_type == 'parser':
            for event_json in self.get_output_queue():
                event = message.MessageFactory.unserialize(event_json)
                self.assertIsInstance(event, message.Event)
                self.assertIn('classification.type', event)
                self.assertIn('raw', event)

        """ Test if bot log messages are correctly formatted. """
        self.assertLoglineMatches(0, "{} initialized with id {} and version"
                                     " [0-9.]{{5}} \([a-zA-Z0-9,:. ]+\)( \[GCC\])?"
                                     " as process [0-9]+\."
                                     "".format(self.bot_name,
                                               self.bot_id), "INFO")
        self.assertRegexpMatchesLog("INFO - Bot is starting.")
        self.assertLoglineEqual(-1, "Bot stopped.", "INFO")
        self.assertNotRegexpMatchesLog("(ERROR.*?){%d}" % (self.allowed_error_count + 1))
        self.assertNotRegexpMatchesLog("CRITICAL")
        """ If no error happened (incl. tracebacks, we can check for formatting) """
        if not self.allowed_error_count:  # This would fail for tracebacks currently
            for logline in self.loglines:
                fields = utils.parse_logline(logline)
                self.assertTrue(fields['message'][-1] in '.:?!',
                                msg='Logline {!r} does not end with .? or !.'
                                    ''.format(fields['message']))
                self.assertTrue(fields['message'].upper() == fields['message'].upper(),
                                msg='Logline {!r} does not beginn with an upper case char.'
                                    ''.format(fields['message']))
Beispiel #16
0
    def test_parse_logline_syslog(self):
        """Tests if the parse_logline() function parses syslog correctly. """
        line = ("Feb 22 10:17:10 host malware-domain-list-collector: ERROR "
                "Something went wrong")

        actual = utils.parse_logline(line, regex=utils.SYSLOG_REGEX)
        self.assertEqual({'bot_id': 'malware-domain-list-collector',
                          'date': '%d-02-22T10:17:10' % datetime.datetime.now().year,
                          'log_level': 'ERROR',
                          'message': 'Something went wrong'}, actual)
Beispiel #17
0
    def test_parse_logline(self):
        """Tests if the parse_logline() function works as expected"""
        line = ("2015-05-29 21:00:24,379 - malware-domain-list-collector - "
                "ERROR - Something went wrong")

        fields = utils.parse_logline(line)
        self.assertDictEqual({'asctime': '2015-05-29 21:00:24,379',
                              'name': 'malware-domain-list-collector',
                              'levelname': 'ERROR',
                              'message': 'Something went wrong'},
                             fields)
Beispiel #18
0
    def test_parse_logline(self):
        """Tests if the parse_logline() function works as expected"""
        line = ("2015-05-29 21:00:24,379 - malware-domain-list-collector - "
                "ERROR - Something went wrong")

        fields = utils.parse_logline(line)
        self.assertDictEqual({'date': '2015-05-29 21:00:24,379',
                              'bot_id': 'malware-domain-list-collector',
                              'log_level': 'ERROR',
                              'message': 'Something went wrong'},
                             fields)
Beispiel #19
0
    def assertLogMatches(self, pattern, levelname="ERROR"):
        """Asserts if any logline matches a specific requirement.
           Args:
                pattern: Message text which is compared
                type: Type of logline which is asserted"""

        self.assertIsNotNone(self.loglines)
        for logline in self.loglines:
            fields = utils.parse_logline(logline)

            if levelname == fields["log_level"] and re.match(pattern, fields["message"]):
                break
        else:
            raise ValueError('No matching logline found.')
Beispiel #20
0
    def assertAnyLoglineEqual(self, message, levelname="ERROR"):
        """Asserts if any logline matches a specific requirement.
           Args:
                message: Message text which is compared
                type: Type of logline which is asserted"""

        self.assertIsNotNone(self.loglines)
        for logline in self.loglines:
            fields = utils.parse_logline(logline)

            if levelname == fields["log_level"] and message == fields["message"]:
                return
        else:
            raise ValueError('Logline with level {!r} and message {!r} not found'
                             ''.format(levelname, message))
Beispiel #21
0
    def assertLoglineMatches(self, line_no, pattern, levelname="ERROR"):
        """Asserts if a logline matches a specific requirement.
           Args:
                line_no: Number of the logline which is asserted
                pattern: Message text which is compared
                type: Type of logline which is asserted"""

        self.assertIsNotNone(self.loglines)
        logline = self.loglines[line_no]
        fields = utils.parse_logline(logline)

        self.assertEqual(
            self.bot_id, fields["bot_id"], "bot_id %s didn't match %s"
            "".format(self.bot_id, fields["bot_id"]))

        self.assertEqual(levelname, fields["log_level"])
        self.assertRegex(fields["message"], pattern)
Beispiel #22
0
    def assertLoglineMatches(self, line_no, pattern, levelname="ERROR"):
        """Asserts if a logline matches a specific requirement.
           Args:
                line_no: Number of the logline which is asserted
                pattern: Message text which is compared
                type: Type of logline which is asserted"""

        self.assertIsNotNone(self.loglines)
        logline = self.loglines[line_no]
        fields = utils.parse_logline(logline)

        self.assertEqual(self.bot_id, fields["bot_id"],
                         "bot_id %s didn't match %s"
                         "".format(self.bot_id, fields["bot_id"]))

        self.assertEqual(levelname, fields["log_level"])
        self.assertRegex(fields["message"], pattern)
Beispiel #23
0
    def assertLoglineEqual(self, line_no: int, message: str, levelname: str = "ERROR"):
        """
        Asserts if a logline matches a specific requirement.

        Parameters:
            line_no: Number of the logline which is asserted
            message: Message text which is compared
            levelname: Log level of logline which is asserted
        """

        self.assertIsNotNone(self.loglines)
        logline = self.loglines[line_no]
        fields = utils.parse_logline(logline)

        self.assertEqual(self.bot_id, fields["bot_id"],
                         "bot_id %s didn't match %s"
                         "".format(self.bot_id, fields["bot_id"]))

        self.assertEqual(levelname, fields["log_level"])
        self.assertEqual(message, fields["message"])
Beispiel #24
0
    def assertLogMatches(self, pattern: str, levelname: str = "ERROR"):
        """
        Asserts if any logline matches a specific requirement.

        Parameters:
            pattern: Message text which is compared, regular expression.
            levelname: Log level of the logline which is asserted, upper case.
        """
        self.assertIsNotNone(self.loglines)
        for logline in self.loglines:
            fields = utils.parse_logline(logline)

            #  Exception tracebacks
            if isinstance(fields, str):
                if levelname == "ERROR" and re.match(pattern, fields):
                    break
            elif levelname == fields["log_level"] and re.match(pattern, fields["message"]):
                break
        else:
            raise ValueError('No matching logline found.')  # pragma: no cover
Beispiel #25
0
    def assertLogMatches(self, pattern: str, levelname: str = "ERROR"):
        """
        Asserts if any logline matches a specific requirement.

        Parameters:
            pattern: Message text which is compared, regular expression.
            levelname: Log level of the logline which is asserted, upper case.
        """

        self.assertIsNotNone(self.loglines)
        for logline in self.loglines:
            fields = utils.parse_logline(logline)

            #  Exception tracebacks
            if isinstance(fields, str):
                if levelname == "ERROR" and re.match(pattern, fields):
                    break
            elif levelname == fields["log_level"] and re.match(pattern, fields["message"]):
                break
        else:
            raise ValueError('No matching logline found.')
Beispiel #26
0
    def run_bot(self,
                iterations: int = 1,
                error_on_pipeline: bool = False,
                prepare=True,
                parameters={}):
        """
        Call this method for actually doing a test run for the specified bot.

        Parameters:
            iterations: Bot instance will be run the given times, defaults to 1.
            parameters: passed to prepare_bot
        """
        if prepare:
            self.prepare_bot(parameters=parameters)
        with mock.patch('intelmq.lib.utils.load_configuration',
                        new=self.mocked_config):
            with mock.patch('intelmq.lib.utils.log', self.mocked_log):
                for run in range(iterations):
                    self.bot.start(error_on_pipeline=error_on_pipeline,
                                   source_pipeline=self.pipe,
                                   destination_pipeline=self.pipe)
        self.loglines_buffer = self.log_stream.getvalue()
        self.loglines = self.loglines_buffer.splitlines()
        """ Test if input queue is empty. """
        self.assertEqual(
            self.input_queue, [],
            'Not all input messages have been processed. '
            'You probably need to increase the number of '
            'iterations of `run_bot`.')
        """ Test if report has required fields. """
        if self.bot_type == 'collector':
            for report_json in self.get_output_queue():
                report = message.MessageFactory.unserialize(
                    report_json, harmonization=self.harmonization)
                self.assertIsInstance(report, message.Report)
                self.assertIn('feed.name', report)
                self.assertIn('raw', report)
                self.assertIn('time.observation', report)
        """ Test if event has required fields. """
        if self.bot_type == 'parser':
            for event_json in self.get_output_queue():
                event = message.MessageFactory.unserialize(
                    event_json, harmonization=self.harmonization)
                self.assertIsInstance(event, message.Event)
                self.assertIn('classification.type', event)
                self.assertIn('raw', event)
        """ Test if bot log messages are correctly formatted. """
        self.assertLoglineMatches(
            0, "{} initialized with id {} and intelmq [0-9a-z.]* and python"
            r" [0-9a-z.]{{5,8}}\+? \([a-zA-Z0-9,:. ]+\)( \[GCC\])?"
            r" as process [0-9]+\."
            "".format(self.bot_name, self.bot_id), "INFO")
        self.assertRegexpMatchesLog("INFO - Bot is starting.")
        self.assertLoglineEqual(-1, "Bot stopped.", "INFO")
        self.assertNotRegexpMatchesLog("(ERROR.*?){%d}" %
                                       (self.allowed_error_count + 1))
        self.assertNotRegexpMatchesLog("(WARNING.*?){%d}" %
                                       (self.allowed_warning_count + 1))
        self.assertNotRegexpMatchesLog("CRITICAL")
        """ If no error happened (incl. tracebacks) we can check for formatting """
        if not self.allowed_error_count:
            for logline in self.loglines:
                fields = utils.parse_logline(logline)
                if not isinstance(fields, dict):
                    # Traceback
                    continue
                self.assertTrue(fields['message'][-1] in '.:?!',
                                msg='Logline {!r} does not end with .? or !.'
                                ''.format(fields['message']))
                self.assertTrue(
                    fields['message'].upper() == fields['message'].upper(),
                    msg='Logline {!r} does not begin with an upper case char.'
                    ''.format(fields['message']))
Beispiel #27
0
    def run_bot(self, iterations: int = 1, error_on_pipeline: bool = False, prepare=True):
        """
        Call this method for actually doing a test run for the specified bot.

        Parameters:
            iterations: Bot instance will be run the given times, defaults to 1.
        """
        if prepare:
            self.prepare_bot()
        with mock.patch('intelmq.lib.utils.load_configuration',
                        new=self.mocked_config):
            with mock.patch('intelmq.lib.utils.log', self.mocked_log):
                for run in range(iterations):
                    self.bot.start(error_on_pipeline=error_on_pipeline,
                                   source_pipeline=self.pipe,
                                   destination_pipeline=self.pipe)
        self.loglines_buffer = self.log_stream.getvalue()
        self.loglines = self.loglines_buffer.splitlines()

        """ Test if all pipes are created with correct names. """
        pipenames = ["{}-input", "{}-input-internal", "{}-output", "{}-other-output", "{}-way1-output", "{}-way2-output"]
        self.assertSetEqual({x.format(self.bot_id) for x in pipenames},
                            set(self.pipe.state.keys()))
        """ Test if input queue is empty. """
        self.assertEqual(self.input_queue, [],
                         'Not all input messages have been processed. '
                         'You probably need to increase the number of '
                         'iterations of `run_bot`.')

        """ Test if report has required fields. """
        if self.bot_type == 'collector':
            for report_json in self.get_output_queue():
                report = message.MessageFactory.unserialize(report_json,
                                                            harmonization=self.harmonization)
                self.assertIsInstance(report, message.Report)
                self.assertIn('feed.name', report)
                self.assertIn('raw', report)
                self.assertIn('time.observation', report)

        """ Test if event has required fields. """
        if self.bot_type == 'parser':
            for event_json in self.get_output_queue():
                event = message.MessageFactory.unserialize(event_json,
                                                           harmonization=self.harmonization)
                self.assertIsInstance(event, message.Event)
                self.assertIn('classification.type', event)
                self.assertIn('raw', event)

        """ Test if bot log messages are correctly formatted. """
        self.assertLoglineMatches(0, "{} initialized with id {} and intelmq [0-9a-z.]* and python"
                                     r" [0-9a-z.]{{5,8}}\+? \([a-zA-Z0-9,:. ]+\)( \[GCC\])?"
                                     r" as process [0-9]+\."
                                     "".format(self.bot_name,
                                               self.bot_id), "INFO")
        self.assertRegexpMatchesLog("INFO - Bot is starting.")
        self.assertLoglineEqual(-1, "Bot stopped.", "INFO")
        self.assertNotRegexpMatchesLog("(ERROR.*?){%d}" % (self.allowed_error_count + 1))
        self.assertNotRegexpMatchesLog("(WARNING.*?){%d}" % (self.allowed_warning_count + 1))
        self.assertNotRegexpMatchesLog("CRITICAL")
        """ If no error happened (incl. tracebacks) we can check for formatting """
        if not self.allowed_error_count:
            for logline in self.loglines:
                fields = utils.parse_logline(logline)
                if not isinstance(fields, dict):
                    # Traceback
                    continue
                self.assertTrue(fields['message'][-1] in '.:?!',
                                msg='Logline {!r} does not end with .? or !.'
                                    ''.format(fields['message']))
                self.assertTrue(fields['message'].upper() == fields['message'].upper(),
                                msg='Logline {!r} does not begin with an upper case char.'
                                    ''.format(fields['message']))
Beispiel #28
0
    def run_bot(self,
                iterations: int = 1,
                error_on_pipeline: bool = False,
                prepare=True,
                parameters={},
                allowed_error_count=0,
                allowed_warning_count=0,
                stop_bot: bool = True):
        """
        Call this method for actually doing a test run for the specified bot.

        Parameters:
            iterations: Bot instance will be run the given times, defaults to 1.
            parameters: passed to prepare_bot
            allowed_error_count: maximum number allow allowed errors in the logs
            allowed_warning_count: maximum number allow allowed warnings in the logs
            bot_stop: If the bot should be stopped/shut down after running it. Set to False, if you are calling this method again afterwards, as the bot shutdown destroys structures (pipeline, etc.)
        """
        if prepare:
            self.prepare_bot(parameters=parameters)
        elif parameters:
            raise ValueError(
                "Parameter 'parameters' is given, but parameter "
                "'prepare' is false. Parameters must be passed on "
                "to 'prepare_bot' to be effective.")
        with mock.patch('intelmq.lib.utils.load_configuration',
                        new=self.mocked_config):
            with mock.patch('intelmq.lib.utils.log',
                            self.get_mocked_logger(self.logger)):
                for run in range(iterations):
                    self.bot.start(error_on_pipeline=error_on_pipeline,
                                   source_pipeline=self.pipe,
                                   destination_pipeline=self.pipe)
                if stop_bot:
                    self.bot.stop(exitcode=0)
        self.loglines_buffer = self.log_stream.getvalue()
        self.loglines = self.loglines_buffer.splitlines()
        """ Test if input queue is empty. """
        self.assertEqual(
            self.input_queue, [],
            'Not all input messages have been processed. '
            'You probably need to increase the number of '
            'iterations of `run_bot`.')

        internal_queue_size = len(self.get_input_internal_queue())
        self.assertEqual(
            internal_queue_size, 0,
            'The internal input queue is not empty, but has '
            f'{internal_queue_size} element(s). '
            'The bot did not acknowledge all messages.')
        """ Test if report has required fields. """
        if self.bot_type == 'collector':
            for report_json in self.get_output_queue():
                report = message.MessageFactory.unserialize(
                    report_json, harmonization=self.harmonization)
                self.assertIsInstance(report, message.Report)
                self.assertIn('raw', report)
                self.assertIn('time.observation', report)
        """ Test if event has required fields. """
        if self.bot_type == 'parser':
            for event_json in self.get_output_queue():
                event = message.MessageFactory.unserialize(
                    event_json, harmonization=self.harmonization)
                self.assertIsInstance(event, message.Event)
                self.assertIn('classification.type', event)
                self.assertIn('raw', event)
        """ Test if bot log messages are correctly formatted. """
        self.assertLoglineMatches(
            0, "{} initialized with id {} and intelmq [0-9a-z.]* and python"
            r" [0-9a-z.]{{5,8}}\+? \([a-zA-Z0-9,:. ]+\)( \[GCC\])?"
            r" as process [0-9]+\."
            "".format(self.bot_name, self.bot_id), "INFO")
        self.assertRegexpMatchesLog("INFO - Bot is starting.")
        if stop_bot:
            self.assertLoglineEqual(-1, "Bot stopped.", "INFO")

        allowed_error_count = max(allowed_error_count,
                                  self.allowed_error_count)
        self.assertLessEqual(
            len(re.findall(' - ERROR - ', self.loglines_buffer)),
            allowed_error_count)
        allowed_warning_count = max(allowed_warning_count,
                                    self.allowed_warning_count)
        self.assertLessEqual(
            len(re.findall(' - WARNING - ', self.loglines_buffer)),
            allowed_warning_count)
        self.assertNotRegexpMatchesLog("CRITICAL")
        """ If no error happened (incl. tracebacks) we can check for formatting """
        if not self.allowed_error_count:
            for logline in self.loglines:
                fields = utils.parse_logline(logline)
                if not isinstance(fields, dict):
                    # Traceback
                    continue
                self.assertTrue(fields['message'][-1] in '.:?!',
                                msg='Logline {!r} does not end with .? or !.'
                                ''.format(fields['message']))
                self.assertTrue(
                    fields['message'].upper() == fields['message'].upper(),
                    msg='Logline {!r} does not begin with an upper case char.'
                    ''.format(fields['message']))