Beispiel #1
0
    def _dispatch(self, alert, descriptor):
        """Send alert to an SNS topic

        Args:
            alert (Alert): Alert instance which triggered a rule
            descriptor (str): Output descriptor

        Returns:
            bool: True if alert was sent successfully, False otherwise
        """
        # SNS topics can only be accessed via their ARN
        topic_name = self.config[self.__service__][descriptor]
        topic_arn = 'arn:aws:sns:{}:{}:{}'.format(self.region, self.account_id, topic_name)
        topic = boto3.resource('sns', region_name=self.region).Topic(topic_arn)

        publication = compose_alert(alert, self, descriptor)

        # Presentation defaults
        default_subject = '{} triggered alert {}'.format(alert.rule_name, alert.alert_id)
        default_message = json.dumps(publication, indent=2, sort_keys=True)

        # Published presentation fields
        # Subject must be < 100 characters long;
        subject = elide_string_middle(publication.get('@aws-sns.topic', default_subject), 99)
        message = publication.get('@aws-sns.message', default_message)

        topic.publish(
            Message=message,
            Subject=subject
        )

        return True
Beispiel #2
0
    def _standardize_custom_attachments(cls, custom_slack_attachments):
        """Supplies default fields to given attachments and validates their structure.

        You can test out custom attachments using this tool:
          https://api.slack.com/docs/messages/builder

        When publishers provider custom slack attachments to the SlackOutput, it offers increased
        flexibility, but requires more work. Publishers need to pay attention to the following:

        - Slack requires escaping the characters: '&', '>' and '<'
        - Slack messages have a limit of 4000 characters
        - Individual slack messages support a maximum of 20 attachments


        Args:
            custom_slack_attachments (list): A list of dicts that is provided by the publisher.

        Returns:
            list: The value to the "attachments" Slack API argument
        """

        attachments = []

        for custom_slack_attachment in custom_slack_attachments:
            attachment = cls._get_attachment_skeleton()
            attachment.update(custom_slack_attachment)

            # Enforce maximum text length; make sure to check size AFTER escaping in case
            # extra escape characters pushes it over the limit
            if len(attachment['text']) > cls.MAX_MESSAGE_SIZE:
                LOGGER.warning(
                    'Custom attachment was truncated to length %d. Full message: %s',
                    cls.MAX_MESSAGE_SIZE,
                    attachment['text']
                )
                attachment['text'] = elide_string_middle(attachment['text'], cls.MAX_MESSAGE_SIZE)

            attachments.append(attachment)

            # Enforce maximum number of attachments
            if len(attachments) >= cls.MAX_ATTACHMENTS:
                LOGGER.warning(
                    'Message with %d custom attachments was truncated to %d attachments',
                    len(custom_slack_attachments),
                    cls.MAX_ATTACHMENTS
                )
                break

        return attachments
Beispiel #3
0
    def dispatch(self, **kwargs):
        """Send alert to an SNS topic"""
        # SNS topics can only be accessed via their ARN
        topic_name = self.config[self.__service__][kwargs['descriptor']]
        topic_arn = 'arn:aws:sns:{}:{}:{}'.format(self.region, self.account_id,
                                                  topic_name)
        topic = boto3.resource('sns', region_name=self.region).Topic(topic_arn)

        alert = kwargs['alert']
        response = topic.publish(
            Message=json.dumps(alert, indent=2, sort_keys=True),
            # Subject must be < 100 characters long
            Subject=elide_string_middle(
                '{} triggered alert {}'.format(kwargs['rule_name'],
                                               alert['id']), 99))
        return self._log_status(response, kwargs['descriptor'])
Beispiel #4
0
def test_elide_string_middle():
    """Alert Processor - Helpers - String Truncation"""
    alphabet = 'abcdefghijklmnopqrstuvwxyz'

    # String shortened
    assert_equal('ab ... yz', elide_string_middle(alphabet, 10))
    assert_equal('abcde ... vwxyz', elide_string_middle(alphabet, 15))
    assert_equal('abcdefg ... tuvwxyz', elide_string_middle(alphabet, 20))
    assert_equal('abcdefghij ... qrstuvwxyz',
                 elide_string_middle(alphabet, 25))

    # String unchanged
    assert_equal(alphabet, elide_string_middle(alphabet, 26))
    assert_equal(alphabet, elide_string_middle(alphabet, 50))
Beispiel #5
0
    def dispatch(self, alert, descriptor):
        """Send alert to an SNS topic

        Args:
            alert (Alert): Alert instance which triggered a rule
            descriptor (str): Output descriptor

        Returns:
            bool: True if alert was sent successfully, False otherwise
        """
        # SNS topics can only be accessed via their ARN
        topic_name = self.config[self.__service__][descriptor]
        topic_arn = 'arn:aws:sns:{}:{}:{}'.format(self.region, self.account_id, topic_name)
        topic = boto3.resource('sns', region_name=self.region).Topic(topic_arn)

        response = topic.publish(
            Message=json.dumps(alert.output_dict(), indent=2, sort_keys=True),
            # Subject must be < 100 characters long
            Subject=elide_string_middle(
                '{} triggered alert {}'.format(alert.rule_name, alert.alert_id), 99)
        )
        return self._log_status(response, descriptor)