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
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
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))