def test_rule_with_invalid_severity(self) -> None:
        rule_body = 'def rule(event):\n\treturn True\n' \
                    'def alert_context(event):\n\treturn {}\n' \
                    'def title(event):\n\treturn "test_rule_with_invalid_severity"\n' \
                    'def severity(event):\n\treturn "CRITICAL-ISH"\n'
        rule = Rule({
            'id': 'test_rule_with_invalid_severity',
            'body': rule_body,
            'versionId': 'versionId',
            'severity': 'INFO'
        })

        expected_result = RuleResult(
            rule_id='test_rule_with_invalid_severity',
            matched=True,
            alert_context='{}',
            title_output='test_rule_with_invalid_severity',
            dedup_output='test_rule_with_invalid_severity',
            severity_exception=AssertionError(
                "Expected severity to be any of the following: [['INFO', 'LOW', 'MEDIUM', 'HIGH', "
                "'CRITICAL']], got [CRITICAL-ISH] instead."),
            rule_severity='INFO',
        )
        result = rule.run(PantherEvent({}, None), {}, {}, batch_mode=False)
        self.assertEqual(str(expected_result), str(result))
        self.assertTrue(result.errored)
        self.assertIsNotNone(result.severity_exception)
 def test_alert_context_too_big(self) -> None:
     # Function should generate alert_context exceeding limit
     alert_context_function = 'def alert_context(event):\n' \
                              '\ttest_dict = {}\n' \
                              '\tfor i in range(300000):\n' \
                              '\t\ttest_dict[str(i)] = "value"\n' \
                              '\treturn test_dict'
     rule_body = 'def rule(event):\n\treturn True\n{}'.format(
         alert_context_function)
     rule = Rule({
         'id': 'test_alert_context_too_big',
         'body': rule_body,
         'versionId': 'versionId',
         'severity': 'INFO'
     })
     expected_alert_context = json.dumps({
         '_error':
         'alert_context size is [5588890] characters, bigger than maximum of [204800] characters'
     })
     expected_result = RuleResult(
         rule_id='test_alert_context_too_big',
         matched=True,
         dedup_output='defaultDedupString:test_alert_context_too_big',
         alert_context=expected_alert_context,
         rule_severity='INFO')
     self.assertEqual(expected_result,
                      rule.run(PantherEvent({}, None), {}, {}))
 def test_rule_with_severity_raising_exception_unit_test(self) -> None:
     rule_body = 'def rule(event):\n\treturn True\n' \
                 'def title(event):\n\treturn"test_rule_with_severity_raising_exception_unit_test"\n' \
                 'def severity(event):\n\traise AssertionError("something bad happened")\n'
     rule = Rule({
         'id': 'test_rule_with_severity_raising_exception_unit_test',
         'body': rule_body,
         'versionId': 'versionId',
         'severity': 'INFO'
     })
     expected_result = RuleResult(
         rule_id='test_rule_with_severity_raising_exception_unit_test',
         matched=True,
         title_output='test_rule_with_severity_raising_exception_unit_test',
         dedup_output='test_rule_with_severity_raising_exception_unit_test',
         severity_output=None,
         severity_exception=AssertionError("something bad happened"),
         rule_severity='INFO',
     )
     result = rule.run(PantherEvent({}, None), {}, {}, batch_mode=False)
     self.assertTrue(result.errored)
     self.assertIsNotNone(result.severity_exception)
     # Exception instances cannot be compared
     self.assertDataclassEqual(expected_result,
                               result,
                               fields_as_string=('severity_exception', ))
    def test_rule_with_invalid_destinations_type(self) -> None:
        rule_body = 'def rule(event):\n\treturn True\n' \
                    'def alert_context(event):\n\treturn {}\n' \
                    'def title(event):\n\treturn "test_rule_with_valid_severity_case_insensitive"\n' \
                    'def severity(event):\n\treturn "cRiTiCaL"\n' \
                    'def destinations(event):\n\treturn "bad input"\n'
        rule = Rule({
            'id': 'test_rule_with_valid_severity_case_insensitive',
            'body': rule_body,
            'versionId': 'versionId',
            'severity': 'INFO'
        })

        expected_result = RuleResult(
            rule_id='test_rule_with_valid_severity_case_insensitive',
            matched=True,
            alert_context='{}',
            title_output='test_rule_with_valid_severity_case_insensitive',
            dedup_output='test_rule_with_valid_severity_case_insensitive',
            severity_output="CRITICAL",
            destinations_output=None,
            destinations_exception=Exception(
                'rule [{}] function [{}] returned [{}], expected a list'.
                format(rule.rule_id, 'destinations', 'str')),
            rule_severity='INFO')
        result = rule.run(PantherEvent({}, None), {}, {}, batch_mode=False)
        self.assertEqual(str(expected_result), str(result))
        self.assertTrue(result.errored)
        self.assertIsNotNone(result.destinations_exception)
    def test_rule_with_all_generated_fields(self) -> None:
        rule_body = 'def rule(event):\n\treturn True\n' \
                    'def alert_context(event):\n\treturn {}\n' \
                    'def title(event):\n\treturn "test_rule_with_all_generated_fields"\n' \
                    'def description(event):\n\treturn "test description"\n' \
                    'def severity(event):\n\treturn "HIGH"\n' \
                    'def reference(event):\n\treturn "test reference"\n' \
                    'def runbook(event):\n\treturn "test runbook"\n' \
                    'def destinations(event):\n\treturn []'
        rule = Rule({
            'id': 'test_rule_with_all_generated_fields',
            'body': rule_body,
            'versionId': 'versionId',
            'severity': 'INFO'
        })

        expected_result = RuleResult(
            rule_id='test_rule_with_all_generated_fields',
            matched=True,
            alert_context='{}',
            title_output='test_rule_with_all_generated_fields',
            dedup_output='test_rule_with_all_generated_fields',
            description_output='test description',
            severity_output='HIGH',
            reference_output='test reference',
            runbook_output='test runbook',
            destinations_output=["SKIP"],
            rule_severity='INFO',
        )
        self.assertEqual(
            expected_result,
            rule.run(PantherEvent({}, None), {}, {}, batch_mode=False))
 def test_rule_throws_exception(self) -> None:
     rule_body = 'def rule(event):\n\traise Exception("test")'
     rule = Rule({
         'id': 'test_rule_throws_exception',
         'body': rule_body,
         'versionId': 'versionId',
         'severity': 'INFO'
     })
     rule_result = rule.run(PantherEvent({}, None), {}, {})
     self.assertIsNone(rule_result.matched)
     self.assertIsNone(rule_result.dedup_output)
     self.assertIsNotNone(rule_result.rule_exception)
 def test_rule_doesnt_match(self) -> None:
     rule_body = 'def rule(event):\n\treturn False'
     rule = Rule({
         'id': 'test_rule_doesnt_match',
         'body': rule_body,
         'versionId': 'versionId',
         'severity': 'INFO'
     })
     expected_rule = RuleResult(matched=False,
                                rule_id='test_rule_doesnt_match',
                                rule_severity='INFO')
     self.assertEqual(expected_rule, rule.run(PantherEvent({}, None), {},
                                              {}))
 def test_rule_with_dedup(self) -> None:
     rule_body = 'def rule(event):\n\treturn True\ndef dedup(event):\n\treturn "testdedup"'
     rule = Rule({
         'id': 'test_rule_with_dedup',
         'body': rule_body,
         'versionId': 'versionId',
         'severity': 'INFO'
     })
     expected_rule = RuleResult(rule_id='test_rule_with_dedup',
                                matched=True,
                                dedup_output='testdedup',
                                rule_severity='INFO')
     self.assertEqual(expected_rule, rule.run(PantherEvent({}, None), {},
                                              {}))
    def test_dedup_exception_batch_mode(self) -> None:
        rule_body = 'def rule(event):\n\treturn True\ndef dedup(event):\n\traise Exception("test")'
        rule = Rule({
            'id': 'test_dedup_throws_exception',
            'body': rule_body,
            'versionId': 'versionId',
            'severity': 'INFO'
        })

        actual = rule.run(PantherEvent({}, None), {}, {}, batch_mode=False)

        self.assertTrue(actual.matched)
        self.assertIsNotNone(actual.dedup_exception)
        self.assertTrue(actual.errored)
Ejemplo n.º 10
0
    def test_rule_invalid_rule_return(self) -> None:
        rule_body = 'def rule(event):\n\treturn "test"'
        rule = Rule({
            'id': 'test_rule_invalid_rule_return',
            'body': rule_body,
            'versionId': 'versionId',
            'severity': 'INFO'
        })
        rule_result = rule.run(PantherEvent({}, None), {}, {})
        self.assertIsNone(rule_result.matched)
        self.assertIsNone(rule_result.dedup_output)
        self.assertTrue(rule_result.errored)

        expected_short_msg = "Exception('rule [test_rule_invalid_rule_return] function [rule] returned [str], expected [bool]')"
        self.assertEqual(expected_short_msg, rule_result.short_error_message)
        self.assertEqual(rule_result.error_type, 'Exception')
Ejemplo n.º 11
0
    def test_dedup_throws_exception(self) -> None:
        rule_body = 'def rule(event):\n\treturn True\ndef dedup(event):\n\traise Exception("test")'
        rule = Rule({
            'id': 'test_dedup_throws_exception',
            'body': rule_body,
            'versionId': 'versionId',
            'severity': 'INFO'
        })

        expected_rule = RuleResult(
            rule_id='test_dedup_throws_exception',
            matched=True,
            dedup_output='defaultDedupString:test_dedup_throws_exception',
            rule_severity='INFO')
        self.assertEqual(expected_rule, rule.run(PantherEvent({}, None), {},
                                                 {}))
Ejemplo n.º 12
0
    def test_invalid_python_syntax(self) -> None:
        rule_body = 'def rule(test):this is invalid python syntax'
        rule = Rule({
            'id': 'test_invalid_python_syntax',
            'body': rule_body,
            'versionId': 'versionId',
            'severity': 'INFO'
        })
        rule_result = rule.run(PantherEvent({}, None), {}, {})
        self.assertIsNone(rule_result.matched)
        self.assertIsNone(rule_result.dedup_output)
        self.assertIsNone(rule_result.rule_exception)

        self.assertTrue(rule_result.errored)
        self.assertEqual(rule_result.error_type, "SyntaxError")
        self.assertIsNotNone(rule_result.short_error_message)
        self.assertIsNotNone(rule_result.error_message)
Ejemplo n.º 13
0
    def test_create_rule_missing_version(self) -> None:
        exception = False
        try:
            Rule({'id': 'test_create_rule_missing_version', 'body': 'rule'})
        except AssertionError:
            exception = True

        self.assertTrue(exception)
Ejemplo n.º 14
0
    def test_rule_invalid_title_return(self) -> None:
        rule_body = 'def rule(event):\n\treturn True\ndef title(event):\n\treturn {}'
        rule = Rule({
            'id': 'test_rule_invalid_title_return',
            'body': rule_body,
            'versionId': 'versionId',
            'severity': 'INFO'
        })

        expected_result = RuleResult(
            rule_id='test_rule_invalid_title_return',
            matched=True,
            dedup_output='test_rule_invalid_title_return',
            title_output='test_rule_invalid_title_return',
            rule_severity='INFO')
        self.assertEqual(rule.run(PantherEvent({}, None), {}, {}),
                         expected_result)
Ejemplo n.º 15
0
    def test_rule_dedup_returns_empty_string(self) -> None:
        rule_body = 'def rule(event):\n\treturn True\ndef dedup(event):\n\treturn ""'
        rule = Rule({
            'id': 'test_rule_dedup_returns_empty_string',
            'body': rule_body,
            'versionId': 'versionId',
            'severity': 'INFO'
        })

        expected_result = RuleResult(
            rule_id='test_rule_dedup_returns_empty_string',
            matched=True,
            dedup_output=
            'defaultDedupString:test_rule_dedup_returns_empty_string',
            rule_severity='INFO')
        self.assertEqual(rule.run(PantherEvent({}, None), {}, {}),
                         expected_result)
Ejemplo n.º 16
0
    def test_alert_context(self) -> None:
        rule_body = 'def rule(event):\n\treturn True\ndef alert_context(event):\n\treturn {"string": "string", "int": 1, "nested": {}}'
        rule = Rule({
            'id': 'test_alert_context',
            'body': rule_body,
            'versionId': 'versionId',
            'severity': 'INFO'
        })

        expected_result = RuleResult(
            rule_id='test_alert_context',
            matched=True,
            dedup_output='defaultDedupString:test_alert_context',
            alert_context='{"string": "string", "int": 1, "nested": {}}',
            rule_severity='INFO',
        )
        self.assertEqual(expected_result,
                         rule.run(PantherEvent({}, None), {}, {}))
Ejemplo n.º 17
0
    def test_create_rule_missing_method(self) -> None:
        exception = False
        rule_body = 'def another_method(event):\n\treturn False'
        try:
            Rule({'id': 'test_create_rule_missing_method', 'body': rule_body})
        except AssertionError:
            exception = True

        self.assertTrue(exception)
Ejemplo n.º 18
0
    def test_rule_default_dedup_time(self) -> None:
        rule_body = 'def rule(event):\n\treturn True'
        rule = Rule({
            'id': 'test_rule_default_dedup_time',
            'body': rule_body,
            'versionId': 'versionId',
            'severity': 'INFO'
        })

        self.assertEqual(60, rule.rule_dedup_period_mins)
Ejemplo n.º 19
0
    def test_restrict_dedup_size(self) -> None:
        rule_body = 'def rule(event):\n\treturn True\ndef dedup(event):\n\treturn "".join("a" for i in range({}))'. \
            format(MAX_DEDUP_STRING_SIZE + 1)
        rule = Rule({
            'id': 'test_restrict_dedup_size',
            'body': rule_body,
            'versionId': 'versionId',
            'severity': 'INFO'
        })

        expected_dedup_string_prefix = ''.join(
            'a' for _ in range(MAX_DEDUP_STRING_SIZE -
                               len(TRUNCATED_STRING_SUFFIX)))
        expected_rule = RuleResult(rule_id='test_restrict_dedup_size',
                                   matched=True,
                                   dedup_output=expected_dedup_string_prefix +
                                   TRUNCATED_STRING_SUFFIX,
                                   rule_severity='INFO')
        self.assertEqual(expected_rule, rule.run(PantherEvent({}, None), {},
                                                 {}))
Ejemplo n.º 20
0
    def test_rule_tags(self) -> None:
        rule_body = 'def rule(event):\n\treturn True'
        rule = Rule({
            'id': 'test_rule_default_dedup_time',
            'body': rule_body,
            'versionId': 'versionId',
            'tags': ['tag2', 'tag1'],
            'severity': 'INFO'
        })

        self.assertEqual(['tag1', 'tag2'], rule.rule_tags)
Ejemplo n.º 21
0
    def test_rule_with_severity_raising_exception_batch_mode(self) -> None:
        rule_body = 'def rule(event):\n\treturn True\n' \
                    'def title(event):\n\treturn"test_rule_with_severity_raising_exception_batch_mode"\n' \
                    'def severity(event):\n\traise AssertionError("something bad happened")\n'
        rule = Rule({
            'id': 'test_rule_with_severity_raising_exception_batch_mode',
            'body': rule_body,
            'versionId': 'versionId',
            'severity': 'INFO'
        })

        expected_result = RuleResult(
            rule_id='test_rule_with_severity_raising_exception_batch_mode',
            matched=True,
            title_output='test_rule_with_severity_raising_exception_batch_mode',
            dedup_output='test_rule_with_severity_raising_exception_batch_mode',
            severity_output='INFO',
            rule_severity='INFO',
        )
        result = rule.run(PantherEvent({}, None), {}, {}, batch_mode=True)
        self.assertEqual(str(expected_result), str(result))
Ejemplo n.º 22
0
    def test_alert_context_immutable_event(self) -> None:
        alert_context_function = 'def alert_context(event):\n' \
                                 '\treturn {"headers": event["headers"],\n' \
                                 '\t\t"get_params": event["query_string_args"]}'
        rule_body = 'def rule(event):\n\treturn True\n{}'.format(
            alert_context_function)
        rule = Rule({
            'id': 'test_alert_context_immutable_event',
            'body': rule_body,
            'versionId': 'versionId',
            'severity': 'INFO'
        })
        event = {
            'headers': {
                'User-Agent': 'Chrome'
            },
            'query_string_args': [{
                'a': '1'
            }, {
                'b': '2'
            }]
        }

        expected_alert_context = json.dumps({
            'headers':
            event['headers'],
            'get_params':
            event['query_string_args']
        })
        expected_result = RuleResult(
            rule_id='test_alert_context_immutable_event',
            matched=True,
            dedup_output=
            'defaultDedupString:test_alert_context_immutable_event',
            alert_context=expected_alert_context,
            rule_severity='INFO',
        )
        self.assertEqual(expected_result,
                         rule.run(PantherEvent(event, None), {}, {}))
Ejemplo n.º 23
0
    def test_alert_context_returns_full_event(self) -> None:
        alert_context_function = 'def alert_context(event):\n\treturn event'
        rule_body = 'def rule(event):\n\treturn True\n{}'.format(
            alert_context_function)
        rule = Rule({
            'id': 'test_alert_context_returns_full_event',
            'body': rule_body,
            'versionId': 'versionId',
            'severity': 'INFO'
        })
        event = {'test': 'event'}

        expected_alert_context = json.dumps(event)
        expected_result = RuleResult(
            rule_id='test_alert_context_returns_full_event',
            matched=True,
            dedup_output=
            'defaultDedupString:test_alert_context_returns_full_event',
            alert_context=expected_alert_context,
            rule_severity='INFO')
        self.assertEqual(expected_result,
                         rule.run(PantherEvent(event, None), {}, {}))
Ejemplo n.º 24
0
    def test_rule_with_valid_severity_case_insensitive(self) -> None:
        rule_body = 'def rule(event):\n\treturn True\n' \
                    'def alert_context(event):\n\treturn {}\n' \
                    'def title(event):\n\treturn "test_rule_with_valid_severity_case_insensitive"\n' \
                    'def severity(event):\n\treturn "cRiTiCaL"\n'
        rule = Rule({
            'id': 'test_rule_with_valid_severity_case_insensitive',
            'body': rule_body,
            'versionId': 'versionId',
            'severity': 'INFO'
        })

        expected_result = RuleResult(
            matched=True,
            rule_id='test_rule_with_valid_severity_case_insensitive',
            alert_context='{}',
            title_output='test_rule_with_valid_severity_case_insensitive',
            dedup_output='test_rule_with_valid_severity_case_insensitive',
            severity_output="CRITICAL",
            rule_severity='INFO')
        result = rule.run(PantherEvent({}, None), {}, {})
        self.assertEqual(expected_result, result)
Ejemplo n.º 25
0
    def test_rule_matches(self) -> None:
        rule_body = 'def rule(event):\n\treturn True'
        rule = Rule({
            'id': 'test_rule_matches',
            'body': rule_body,
            'dedupPeriodMinutes': 100,
            'versionId': 'test',
            'severity': 'INFO'
        })

        self.assertEqual('test_rule_matches', rule.rule_id)
        self.assertEqual(rule_body, rule.rule_body)
        self.assertEqual('test', rule.rule_version)
        self.assertEqual(100, rule.rule_dedup_period_mins)

        expected_rule = RuleResult(
            rule_id='test_rule_matches',
            matched=True,
            dedup_output='defaultDedupString:test_rule_matches',
            rule_severity='INFO',
        )
        self.assertEqual(expected_rule, rule.run(PantherEvent({}, None), {},
                                                 {}))
Ejemplo n.º 26
0
    def test_alert_context_invalid_return_value(self) -> None:
        rule_body = 'def rule(event):\n\treturn True\ndef alert_context(event):\n\treturn ""'
        rule = Rule({
            'id': 'test_alert_context_invalid_return_value',
            'body': rule_body,
            'versionId': 'versionId',
            'severity': 'INFO'
        })

        expected_alert_context = json.dumps({
            '_error':
            'Exception(\'rule [test_alert_context_invalid_return_value] function [alert_context] returned [str], expected [Mapping]\')'  # pylint: disable=C0301
        })
        expected_result = RuleResult(
            rule_id='test_alert_context_invalid_return_value',
            matched=True,
            dedup_output=
            'defaultDedupString:test_alert_context_invalid_return_value',
            alert_context=expected_alert_context,
            rule_severity='INFO',
        )
        self.assertEqual(expected_result,
                         rule.run(PantherEvent({}, None), {}, {}))
Ejemplo n.º 27
0
    def test_rule_reports(self) -> None:
        rule_body = 'def rule(event):\n\treturn True'
        rule = Rule({
            'id': 'test_rule_default_dedup_time',
            'body': rule_body,
            'versionId': 'versionId',
            'reports': {
                'key1': ['value2', 'value1'],
                'key2': ['value1']
            },
            'severity': 'INFO'
        })

        self.assertEqual({
            'key1': ['value1', 'value2'],
            'key2': ['value1']
        }, rule.rule_reports)