def test_override_default_body_html(self): """SESOutput - Override body html""" rule_name = 'test_override_body_html' alert = get_random_alert(10, rule_name, omit_rule_desc=True) output = MagicMock(spec=SESOutput) alert_publication = compose_alert(alert, output, self.DESCRIPTOR) alert_publication['@aws-ses.body'] = { 'html': '<head><body><p>i am a test</p></body></head>' } msg = SESOutput._build_email(alert, alert_publication, self.CREDS) # Tests payloads = msg.get_payload() for payload in payloads: if payload.is_multipart(): # should only be one payload on this multipart html = payload.get_payload()[0].get_payload() assert_equal(html, '<head><body><p>i am a test</p></body></head>') break else: # Raise an error if no payload of type MIMEText is found raise AssertionError
def test_build_email_from_email(self): """SESOutput - Test sender""" rule_name = 'test_sender' alert = get_random_alert(10, rule_name, omit_rule_desc=True) output = MagicMock(spec=SESOutput) alert_publication = compose_alert(alert, output, self.DESCRIPTOR) msg = SESOutput._build_email(alert, alert_publication, self.CREDS) # verify to_emails is set assert_equal(msg['From'], self.CREDS['from_email'])
def test_format_message_default_rule_description(self): """SlackOutput - Format Message, Default Rule Description""" rule_name = 'test_empty_rule_description' alert = get_random_alert(10, rule_name, True) output = MagicMock(spec=SlackOutput) alert_publication = compose_alert(alert, output, 'asdf') loaded_message = SlackOutput._format_message(alert, alert_publication) # tests default_rule_description = '*Rule Description:*\nNo rule description provided\n' assert_equal(loaded_message['attachments'][0]['pretext'], default_rule_description)
def test_format_message_additional_sections(self, _, alert_section_mock, record_section_mock, add_sections_mock): """TeamsOutput - Format Message - Additional card sections""" rule_name = 'test_rule_default' alert = get_random_alert(25, rule_name) output = MagicMock(spec=TeamsOutput) alert_publication = compose_alert(alert, output, 'asdf') alert_publication['@teams.with_record'] = True # Setup test_card_section test_card_section = Mock() alert_section_mock.return_value = 'Alert_Section' record_section_mock.return_value = 'Record_Section' add_sections_mock.side_effect = (lambda teams_card, _: teams_card) # Pass card section in via Publisher alert_publication['@teams.additional_card_sections'] = [ test_card_section ] loaded_message = self._dispatcher._format_message( alert, alert_publication, self.CREDS['url']) # Tests # Verify title loaded_message.title.assert_called() loaded_message.title.assert_called_with( 'StreamAlert Rule Triggered: {}'.format(alert.rule_name)) # Verify text/description loaded_message.text.assert_called() loaded_message.text.assert_called_with(alert.rule_description) # Verify card color loaded_message.color.assert_called() loaded_message.color.assert_called_with('E81123') # Verify Sections alert_section_mock.assert_called() alert_section_mock.assert_called_with(alert) record_section_mock.assert_called() record_section_mock.assert_called_with(alert.record) add_sections_mock.assert_called() assert_equal(add_sections_mock.call_count, 1) loaded_message.addSection.assert_called() loaded_message.addSection.assert_has_calls( [call('Alert_Section'), call('Record_Section')], any_order=False)
def test_build_email_to_emails_single(self): """SESOutput - Single recipient""" rule_name = 'test_single_recipient' alert = get_random_alert(10, rule_name, omit_rule_desc=True) output = MagicMock(spec=SESOutput) alert_publication = compose_alert(alert, output, self.DESCRIPTOR) msg = SESOutput._build_email(alert, alert_publication, self.CREDS) # verify to_emails is set assert_equal(msg['To'], '*****@*****.**')
def test_subject_override(self): """SESOutput - Change default Subject""" rule_name = 'test_subject_override' alert = get_random_alert(10, rule_name, omit_rule_desc=True) output = MagicMock(spec=SESOutput) alert_publication = compose_alert(alert, output, 'asdf') alert_publication['@aws-ses.subject'] = 'this is a test' msg = SESOutput._build_email(alert, alert_publication, self.CREDS) # check subject override worked assert_equal(msg['Subject'], 'this is a test')
def test_format_message_custom_attachment(self): """SlackOutput - Format Message, Custom Attachment""" rule_name = 'test_empty_rule_description' alert = get_random_alert(10, rule_name, True) output = MagicMock(spec=SlackOutput) alert_publication = compose_alert(alert, output, 'asdf') alert_publication['@slack.attachments'] = [{'text': 'aasdfkjadfj'}] loaded_message = SlackOutput._format_message(alert, alert_publication) # tests assert_equal(len(loaded_message['attachments']), 1) assert_equal(loaded_message['attachments'][0]['text'], 'aasdfkjadfj')
def test_format_message_single(self): """SlackOutput - Format Single Message - Slack""" rule_name = 'test_rule_single' alert = get_random_alert(25, rule_name) output = MagicMock(spec=SlackOutput) alert_publication = compose_alert(alert, output, 'asdf') loaded_message = SlackOutput._format_message(alert, alert_publication) # tests assert_set_equal(set(loaded_message.keys()), {'text', 'mrkdwn', 'attachments'}) assert_equal(loaded_message['text'], '*StreamAlert Rule Triggered: test_rule_single*') assert_equal(len(loaded_message['attachments']), 1)
def test_format_message_custom_text(self): """SlackOutput - Format Single Message - Custom Text""" rule_name = 'test_rule_single' alert = get_random_alert(25, rule_name) output = MagicMock(spec=SlackOutput) alert_publication = compose_alert(alert, output, 'asdf') alert_publication['@slack.text'] = 'Lorem ipsum foobar' loaded_message = SlackOutput._format_message(alert, alert_publication) # tests assert_set_equal(set(loaded_message.keys()), {'text', 'mrkdwn', 'attachments'}) assert_equal(loaded_message['text'], 'Lorem ipsum foobar') assert_equal(len(loaded_message['attachments']), 1)
def test_build_email_to_emails_multiple(self): """SESOutput - Multiple recipients""" rule_name = 'test_multiple_recipients' alert = get_random_alert(10, rule_name, omit_rule_desc=True) output = MagicMock(spec=SESOutput) alert_publication = compose_alert(alert, output, self.DESCRIPTOR) creds = { 'to_emails': '[email protected],[email protected]', 'from_email': '*****@*****.**' } msg = SESOutput._build_email(alert, alert_publication, creds) # verify to_emails is set assert_equal(msg["To"], creds["to_emails"])
def test_format_message_multiple(self): """SlackOutput - Format Multi-Message""" rule_name = 'test_rule_multi-part' alert = get_random_alert(30, rule_name) output = MagicMock(spec=SlackOutput) alert_publication = compose_alert(alert, output, 'asdf') loaded_message = SlackOutput._format_message(alert, alert_publication) # tests assert_set_equal(set(loaded_message.keys()), {'text', 'mrkdwn', 'attachments'}) assert_equal(loaded_message['text'], '*StreamAlert Rule Triggered: test_rule_multi-part*') assert_equal(len(loaded_message['attachments']), 2) assert_equal( loaded_message['attachments'][1]['text'].split('\n')[3][1:7], '000028')
def test_generate_record_section(self, section_mock): """TeamsOutput - _generate_record_section - Teams""" section_mock.return_value = Mock(activityTitle=Mock(), addFact=Mock()) rule_name = 'test_rule_default' alert = get_random_alert(25, rule_name) section = self._dispatcher._generate_record_section(alert.record) # Tests section_mock.assert_called() section.activityTitle.assert_called() section.activityTitle.assert_called_with('StreamAlert Alert Record') section.addFact.assert_called() section.addFact.assert_has_calls( [call(key, value) for key, value in alert.record.items()], any_order=True)
def test_no_attachment(self): """SESOutput - No attachment""" rule_name = 'test_no_attachment' alert = get_random_alert(10, rule_name, omit_rule_desc=True) output = MagicMock(spec=SESOutput) alert_publication = compose_alert(alert, output, self.DESCRIPTOR) # remove the default record alert_publication['@aws-ses.attach_record'] = False msg = SESOutput._build_email(alert, alert_publication, self.CREDS) payloads = msg.get_payload() # Verify no attachment assert_equal(len(payloads), 1) assert_equal(payloads[0].get_payload(), 'Please review the attached record.json')
def test_format_message_custom_attachment_limit(self, log_warning): """SlackOutput - Format Message, Custom Attachment is Truncated""" rule_name = 'test_empty_rule_description' alert = get_random_alert(10, rule_name, True) output = MagicMock(spec=SlackOutput) alert_publication = compose_alert(alert, output, 'asdf') long_message = 'a' * (SlackOutput.MAX_MESSAGE_SIZE + 1) alert_publication['@slack.attachments'] = [{'text': long_message}] loaded_message = SlackOutput._format_message(alert, alert_publication) # tests assert_equal(len(loaded_message['attachments'][0]['text']), 3999) # bug in elide log_warning.assert_called_with( 'Custom attachment was truncated to length %d. Full message: %s', SlackOutput.MAX_MESSAGE_SIZE, long_message)
def test_add_single_attachment(self): """SESOutput - Test single attachment""" rule_name = 'test_single_attachment' alert = get_random_alert(10, rule_name, omit_rule_desc=True) output = MagicMock(spec=SESOutput) alert_publication = compose_alert(alert, output, self.DESCRIPTOR) msg = SESOutput._build_email(alert, alert_publication, self.CREDS) # Verify attachment payloads = msg.get_payload() for payload in payloads: if isinstance(payload, MIMEApplication): assert_equal(payload.get_filename(), 'record.json') break else: # Raise an error if no payload of type MIMEApplication is found raise AssertionError
def test_generate_alert_section(self, section_mock): """TeamsOutput - _generate_alert_section - Teams""" section_mock.return_value = Mock(activityTitle=Mock(), addFact=Mock()) rule_name = 'test_rule_default' alert = get_random_alert(25, rule_name) section = self._dispatcher._generate_alert_section(alert) # Tests section_mock.assert_called() section.activityTitle.assert_called() section.activityTitle.assert_called_with('Alert Info') section.addFact.assert_called() section.addFact.assert_has_calls([ call('rule_name', alert.rule_name), call('alert_id', alert.alert_id) ], any_order=False)
def test_format_message_custom_attachment_multi_limit(self, log_warning): """SlackOutput - Format Message, Too many Custom Attachments is truncated""" rule_name = 'test_empty_rule_description' alert = get_random_alert(10, rule_name, True) output = MagicMock(spec=SlackOutput) alert_publication = compose_alert(alert, output, 'asdf') alert_publication['@slack.attachments'] = [] for _ in range(SlackOutput.MAX_ATTACHMENTS + 1): alert_publication['@slack.attachments'].append({'text': 'yay'}) loaded_message = SlackOutput._format_message(alert, alert_publication) # tests assert_equal(len(loaded_message['attachments']), SlackOutput.MAX_ATTACHMENTS) assert_equal(loaded_message['attachments'][19]['text'], 'yay') log_warning.assert_called_with( 'Message with %d custom attachments was truncated to %d attachments', SlackOutput.MAX_ATTACHMENTS + 1, SlackOutput.MAX_ATTACHMENTS)
def test_override_default_body_string(self): """SESOutput - Override body string""" rule_name = 'test_override_body_string' alert = get_random_alert(10, rule_name, omit_rule_desc=True) output = MagicMock(spec=SESOutput) alert_publication = compose_alert(alert, output, self.DESCRIPTOR) alert_publication['@aws-ses.body'] = 'i am a test' msg = SESOutput._build_email(alert, alert_publication, self.CREDS) # Tests payloads = msg.get_payload() for payload in payloads: if isinstance(payload, MIMEText): assert_equal(payload.get_payload(), 'i am a test') break else: # Raise an error if no payload of type MIMEText is found raise AssertionError
def test_format_message_custom_color(self, _, alert_section_mock, record_section_mock): """TeamsOutput - Format Message - Custom color""" rule_name = 'test_rule_default' alert = get_random_alert(25, rule_name) output = MagicMock(spec=TeamsOutput) alert_publication = compose_alert(alert, output, 'asdf') alert_publication['@teams.card_color'] = '46eb34' alert_section_mock.return_value = 'Alert_Section' record_section_mock.return_value = 'Record_Section' loaded_message = self._dispatcher._format_message( alert, alert_publication, self.CREDS['url']) # Tests # Verify title loaded_message.title.assert_called() loaded_message.title.assert_called_with( 'StreamAlert Rule Triggered: {}'.format(alert.rule_name)) # Verify text/description loaded_message.text.assert_called() loaded_message.text.assert_called_with(alert.rule_description) # Verify card color loaded_message.color.assert_called() loaded_message.color.assert_called_with('46eb34') # Verify Sections alert_section_mock.assert_called() alert_section_mock.assert_called_with(alert) record_section_mock.assert_called() record_section_mock.assert_called_with(alert.record) loaded_message.addSection.assert_called() loaded_message.addSection.assert_has_calls( [call('Alert_Section'), call('Record_Section')], any_order=False)
def test_add_multiple_attachments(self): """SESOutput - Multiple attachments""" rule_name = 'test_multiple_attachments' alert = get_random_alert(10, rule_name, omit_rule_desc=True) output = MagicMock(spec=SESOutput) alert_publication = compose_alert(alert, output, self.DESCRIPTOR) # remove the default record alert_publication['@aws-ses.attach_record'] = False attachments = { 'file_one.json': '{"test": true, "foo": "bar"}', 'file_two.json': '{"test": true, "bar": "foo"}' } alert_publication['@aws-ses.attachments'] = attachments msg = SESOutput._build_email(alert, alert_publication, self.CREDS) # Tests payloads = msg.get_payload() for payload in payloads: if isinstance(payload, MIMEApplication): assert_true(payload.get_filename() in attachments.keys())