Example #1
0
def test_validate_config(app):
    @app.register_parser('test1')
    class TestParser:
        pass

    assert app.parsers
    app.validate_config()
    assert not app.parsers

    app = Comet()

    app.register_parser('test1', TestParser)

    @app.register_router('test1')
    def test_router(*args):
        pass

    app.validate_config()
    assert app.parsers
Example #2
0
def test_validate_config(app):
    @app.register_parser('test1')
    def parse_message(message):
        pass

    assert app.parsers
    app.validate_config()
    assert not app.parsers

    app = Comet()

    app.register_parser('test1', parse_message)

    @app.register_router('test1')
    def test_router(*args):
        pass

    app.validate_config()
    assert app.parsers
Example #3
0
from datetime import timedelta

from comet_common.comet_input_google_pubsub import PubSubInput
from comet_common.comet_parser_detectify import DetectifySchema
from comet_common.comet_parser_forseti import ForsetiSchema
from comet_core import Comet
from comet_core.fingerprint import comet_event_fingerprint

LOG = logging.getLogger(__name__)
LOG.setLevel(
    logging.DEBUG
)  # you might want to change the level to logging.INFO when running in production

LOG.info('Setting up Comet...')

APP = Comet(database_uri='sqlite:///comet-example.db'
            )  # use any other database backend here that SQLAlchemy supports

LOG.info('Created app instance.')


# Outputs
def send_email(recipient, subject, body):
    """Send email to recipient with given subject and body - implement your email sending or other outputs channel here.

    Args:
      recipient (str): recipient email address
      subject (str): email subject line
      body (str): email body
    """
    LOG.debug(
        f'Sending email to {recipient} with subject {subject}: {body[:100]}...'
Example #4
0
def test_handle_non_addressed_events():
    app = Comet()

    @app.register_parser('real_time_source')
    def parse_message(message):
        data = json.loads(message)
        return data, {}

    @app.register_parser('real_time_source2')
    def parse_message(message):
        data = json.loads(message)
        return data, {}

    @app.register_config_provider('real_time_source')
    def register_conf(event):
        return {"escalate_cadence": timedelta(minutes=45)}

    @app.register_config_provider('real_time_source2')
    def register_conf(event):
        return {"escalate_cadence": timedelta(minutes=45)}

    app.register_real_time_source('real_time_source')
    app.register_real_time_source('real_time_source2')

    escalator = mock.Mock()
    escalator2 = mock.Mock()
    app.register_escalator('real_time_source', func=escalator)
    app.register_escalator('real_time_source2', func=escalator2)

    already_processed_user = '******'

    # already processed real time event - needs escalation
    app.data_store.add_record(
        EventRecord(id=2,
                    received_at=datetime.utcnow() - timedelta(hours=1),
                    source_type='real_time_source',
                    owner=already_processed_user,
                    processed_at=datetime.utcnow() - timedelta(hours=1),
                    sent_at=datetime.utcnow() - timedelta(hours=1),
                    data={
                        'search_name': 'alert search name',
                        'name': 'needs escalation'
                    },
                    fingerprint='f2'))

    # already processed real time event - still early for escalation
    # the event sent 35 min ago.
    app.data_store.add_record(
        EventRecord(id=3,
                    received_at=datetime.utcnow() - timedelta(hours=1),
                    source_type='real_time_source2',
                    owner=already_processed_user,
                    processed_at=datetime.utcnow() - timedelta(minutes=35),
                    sent_at=datetime.utcnow() - timedelta(minutes=35),
                    data={
                        'search_name': 'alert search name',
                        'name': 'doesnt need escalation'
                    },
                    fingerprint='f3'))

    app.handle_non_addressed_events()
    assert escalator.call_count == 1
    assert escalator2.call_count == 0
Example #5
0
def test_process_unprocessed_whitelisted_real_time_events():
    app = Comet()
    app.register_parser('real_time_source', json)
    app.register_real_time_source('real_time_source')

    real_time_router = mock.Mock()
    router = mock.Mock()
    escalator = mock.Mock()
    app.register_router('real_time_source', func=real_time_router)
    app.register_router(func=router)
    app.register_escalator(func=escalator)

    check_user = '******'
    # user whitelisted real time event
    app.data_store.add_record(
        EventRecord(id=4,
                    received_at=datetime.utcnow() - timedelta(days=3),
                    sent_at=datetime.utcnow() - timedelta(days=3),
                    source_type='real_time_source',
                    owner=check_user,
                    data={},
                    fingerprint='f4'))

    app.data_store.ignore_event_fingerprint(
        'f4', IgnoreFingerprintRecord.ACCEPT_RISK)

    app.process_unprocessed_events()
    # test the whitelisted event was not routed/escalated
    assert real_time_router.call_count == 0
    assert escalator.call_count == 0
Example #6
0
def test_process_unprocessed_real_time_events():
    app = Comet()
    app.register_parser('real_time_source', json)
    app.register_parser('datastoretest', json)

    app.register_real_time_source('real_time_source')

    real_time_router = mock.Mock()
    router = mock.Mock()
    escalator = mock.Mock()
    app.register_router('real_time_source', func=real_time_router)
    app.register_router(func=router)
    app.register_escalator(func=escalator)

    check_user = '******'
    already_processed_user = '******'

    # already processed regular event
    app.data_store.add_record(
        EventRecord(id=1,
                    received_at=datetime.utcnow() - timedelta(days=5),
                    source_type='datastoretest',
                    owner=already_processed_user,
                    data={},
                    processed_at=datetime.utcnow() - timedelta(days=5),
                    fingerprint='f1'))

    # already processed real time event
    app.data_store.add_record(
        EventRecord(id=2,
                    received_at=datetime.utcnow() - timedelta(days=5),
                    source_type='real_time_source',
                    owner=already_processed_user,
                    processed_at=datetime.utcnow() - timedelta(days=5),
                    data={},
                    fingerprint='f2'))

    # not processed real time event
    app.data_store.add_record(
        EventRecord(id=3,
                    received_at=datetime.utcnow() - timedelta(days=3),
                    source_type='real_time_source',
                    owner=check_user,
                    data={},
                    fingerprint='f3'))

    # real time event needs escalation
    app.data_store.add_record(
        EventRecord(id=4,
                    received_at=datetime.utcnow() - timedelta(days=3),
                    sent_at=datetime.utcnow() - timedelta(days=3),
                    source_type='real_time_source',
                    owner=check_user,
                    data={},
                    fingerprint='f4'))

    app.data_store.ignore_event_fingerprint(
        'f4', IgnoreFingerprintRecord.ESCALATE_MANUALLY)

    app.process_unprocessed_events()
    assert real_time_router.call_count == 1
    # route real time alert with both routers.
    assert router.call_count == 1
    assert real_time_router.call_args[0][2][0].owner == check_user
    assert escalator.call_count == 1
Example #7
0
def test_process_unprocessed_events():
    app = Comet()
    app.register_parser('datastoretest', json)
    app.register_parser('datastoretest2', json)
    app.register_parser('datastoretest3', json)

    app.set_config('datastoretest2', {})

    specific_router = mock.Mock()
    router = mock.Mock()
    escalator = mock.Mock()
    app.register_router('datastoretest2', func=specific_router)
    app.register_router(func=router)
    app.register_escalator(func=escalator)

    check_user = '******'
    already_processed_user = '******'

    app.data_store.add_record(
        EventRecord(id=1,
                    received_at=datetime.utcnow() - timedelta(days=5),
                    source_type='datastoretest',
                    owner=already_processed_user,
                    data={},
                    processed_at=datetime.utcnow() - timedelta(days=5),
                    fingerprint='f1'))

    app.data_store.add_record(
        EventRecord(id=2,
                    received_at=datetime.utcnow() - timedelta(days=4),
                    source_type='datastoretest',
                    owner=already_processed_user,
                    data={},
                    fingerprint='f1'))

    app.data_store.add_record(
        EventRecord(id=3,
                    received_at=datetime.utcnow() - timedelta(days=3),
                    source_type='datastoretest2',
                    owner=check_user,
                    data={},
                    fingerprint='f3'))

    app.data_store.add_record(
        EventRecord(id=4,
                    received_at=datetime.utcnow() - timedelta(days=3),
                    source_type='datastoretest3',
                    owner=check_user,
                    data={},
                    fingerprint='f4'))

    app.process_unprocessed_events()
    assert specific_router.call_count == 1
    assert router.call_count == 2
    assert router.call_args[0][2][0].owner == check_user
    assert escalator.call_count == 3
Example #8
0
def app():
    yield Comet()
Example #9
0
def test_process_unprocessed_events_digest_mode():
    app = Comet()
    app.register_parser("datastoretest", json)
    app.register_parser("datastoretest2", json)
    app.register_parser("datastoretest3", json)
    app.register_parser("datastoretest4", json)

    app.set_config("datastoretest2", {})

    specific_router = mock.Mock()
    router = mock.Mock()
    escalator = mock.Mock()
    app.register_router("datastoretest2", func=specific_router)
    app.register_router(func=router)
    app.register_escalator(func=escalator)

    check_user = "******"
    already_processed_user = "******"

    app.data_store.add_record(
        EventRecord(
            id=1,
            received_at=datetime.utcnow() - timedelta(days=5),
            source_type="datastoretest",
            owner=already_processed_user,
            data={},
            processed_at=datetime.utcnow() - timedelta(days=5),
            fingerprint="f1",
        )
    )

    app.data_store.add_record(
        EventRecord(
            id=2,
            received_at=datetime.utcnow() - timedelta(days=4),
            source_type="datastoretest",
            owner=already_processed_user,
            data={},
            fingerprint="f1",
        )
    )

    app.data_store.add_record(
        EventRecord(
            id=3,
            received_at=datetime.utcnow() - timedelta(days=3),
            source_type="datastoretest2",
            owner=check_user,
            data={},
            fingerprint="f3",
        )
    )

    app.data_store.add_record(
        EventRecord(
            id=4,
            received_at=datetime.utcnow() - timedelta(days=3),
            source_type="datastoretest3",
            owner=check_user,
            data={},
            fingerprint="f4",
        )
    )

    app.process_unprocessed_events()

    # it is expected to have specific_router called once for the datastoretest2
    assert specific_router.call_count == 1
    # it is expected to have two calls of the generic router for the source_type datastoretest2 and datastoretest3
    assert router.call_count == 2
    # and the user must be check_user
    assert router.call_args[0][2][0].owner == check_user
    # due to the default escalation_time=10seconds, all three events (id=2,3,4) must be escalated
    assert escalator.call_count == 3

    app.data_store.add_record(
        EventRecord(
            id=5,
            received_at=datetime.utcnow() - timedelta(days=2),
            source_type="datastoretest",
            owner=check_user,
            data={},
            fingerprint="f1",
        )
    )
    app.process_unprocessed_events()

    # f1 is expected to be processed, but not sent out
    assert app.data_store.get_latest_event_with_fingerprint("f1").processed_at
    assert not app.data_store.get_latest_event_with_fingerprint("f1").sent_at
Example #10
0
def test_process_unprocessed_events_non_digest_mode():
    app = Comet()
    app.register_parser("datastoretest4", json)

    check_user = "******"
    router = mock.Mock()
    escalator = mock.Mock()
    app.register_router(func=router)
    app.register_escalator(func=escalator)

    app.set_config("datastoretest4", {"communication_digest_mode": False, "new_threshold": timedelta(days=14)})

    app.data_store.add_record(
        EventRecord(
            id=6,
            received_at=datetime.utcnow() - timedelta(days=8),
            source_type="datastoretest4",
            sent_at=datetime.utcnow() - timedelta(days=8),
            processed_at=datetime.utcnow() - timedelta(days=8),
            owner=check_user,
            data={},
            fingerprint="f5",
        )
    )

    app.data_store.add_record(
        EventRecord(
            id=7,
            received_at=datetime.utcnow() - timedelta(days=2),
            source_type="datastoretest4",
            owner=check_user,
            data={},
            fingerprint="f5",
        )
    )

    app.data_store.add_record(
        EventRecord(
            id=8,
            received_at=datetime.utcnow(),
            source_type="datastoretest4",
            owner=check_user,
            data={},
            fingerprint="f6",
        )
    )

    app.data_store.add_record(
        EventRecord(
            id=9,
            received_at=datetime.utcnow() - timedelta(days=2),
            source_type="datastoretest4",
            sent_at=datetime.utcnow() - timedelta(days=2),
            processed_at=datetime.utcnow() - timedelta(days=2),
            owner=check_user,
            data={},
            fingerprint="f7",
        )
    )

    app.data_store.add_record(
        EventRecord(
            id=10,
            received_at=datetime.utcnow(),
            source_type="datastoretest4",
            owner=check_user,
            data={},
            fingerprint="f7",
        )
    )

    # f5 is expected to be reminded
    # f6 is expected to be new and sent as well
    # f7 is NOT expected to be reminded
    before_calling = router.call_count
    app.process_unprocessed_events()
    assert app.data_store.get_latest_event_with_fingerprint("f5").processed_at
    assert app.data_store.get_latest_event_with_fingerprint("f6").processed_at
    assert app.data_store.get_latest_event_with_fingerprint("f7").processed_at
    assert router.call_count == before_calling + 1

    sent_fingerprints = [e.fingerprint for e in router.call_args[0][2]]
    assert "f5" in sent_fingerprints
    assert "f6" in sent_fingerprints
    assert "f7" not in sent_fingerprints
Example #11
0
def app() -> Comet:
    """Returns a Comet app."""
    yield Comet()
Example #12
0
def test_handle_non_addressed_events():
    app = Comet()
    app.register_parser('real_time_source', json)
    app.register_parser('real_time_source2', json)
    app.register_real_time_source('real_time_source')
    app.register_real_time_source('real_time_source2')

    app.set_config('real_time_source', {'alerts': {
        'alert search name':
            {
                'escalate_cadence': timedelta(minutes=45),
                'template': 'alerts_template'
            }
    }})
    app.set_config('real_time_source2', {'alerts': {
        'alert search name':
            {
                'escalate_cadence': timedelta(minutes=45),
                'template': 'alerts_template'
            }
    }})
    escalator = mock.Mock()
    escalator2 = mock.Mock()
    app.register_escalator('real_time_source', func=escalator)
    app.register_escalator('real_time_source2', func=escalator2)

    already_processed_user = '******'

    # already processed real time event - needs escalation
    app.data_store.add_record(
        EventRecord(id=2,
                    received_at=datetime.utcnow() - timedelta(hours=1),
                    source_type='real_time_source',
                    owner=already_processed_user,
                    processed_at=datetime.utcnow() - timedelta(hours=1),
                    sent_at=datetime.utcnow() - timedelta(hours=1),
                    data={'search_name': 'alert search name',
                          'name': 'needs escalation'},
                    fingerprint='f2'))

    # already processed real time event - still early for escalation
    # the event sent 35 min ago.
    app.data_store.add_record(
        EventRecord(id=3,
                    received_at=datetime.utcnow() - timedelta(hours=1),
                    source_type='real_time_source2',
                    owner=already_processed_user,
                    processed_at=datetime.utcnow() - timedelta(minutes=35),
                    sent_at=datetime.utcnow() - timedelta(minutes=35),
                    data={'search_name': 'alert search name',
                          'name': 'doesnt need escalation'},
                    fingerprint='f3'))

    app.handle_non_addressed_events()
    assert escalator.call_count == 1
    assert escalator2.call_count == 0