예제 #1
0
파일: run.py 프로젝트: vishnuvp/SnowAlert
def main(target="all", rule_name=None):
    if target == "connector" and rule_name:
        connectors_runner.main(rule_name.upper())

    elif target == "processor":
        alert_processor.main()

    elif target == "dispatcher":
        alert_dispatcher.main()

    elif rule_name and target == "ingest":
        ingest_runner.main(rule_name)

    elif rule_name:
        if rule_name.endswith("_ALERT_QUERY"):
            alert_queries_runner.main(rule_name.upper())

        if rule_name.endswith("_ALERT_SUPPRESSION"):
            alert_suppressions_runner.main(rule_name.upper())

        if rule_name.endswith("_VIOLATION_QUERY"):
            violation_queries_runner.main(rule_name.upper())

        if rule_name.endswith("_VIOLATION_SUPPRESSION"):
            violation_suppressions_runner.main(rule_name.upper())

        if rule_name.endswith("_CONNECTION"):
            connectors_runner.main(rule_name.upper())

        if rule_name.upper().endswith("_BASELINE"):
            baseline_runner.main(rule_name.upper())

    else:
        log.info(f"STARTING RUN WITH ID {RUN_ID}")
        log.info(f"got command {target}")
        if target in ['alert', 'alerts', 'all']:
            alert_queries_runner.main()
            alert_suppressions_runner.main()
            alert_processor.main()
            alert_dispatcher.main()

        if target in ['violation', 'violations', 'all']:
            violation_queries_runner.main()
            violation_suppressions_runner.main()

        if target in ['ingest']:
            ingest_runner.main()
            connectors_runner.main()

        if target in ['connectors', 'all']:
            connectors_runner.main()

        if target in ['baseline', 'baselines', 'all']:
            baseline_runner.main()
예제 #2
0
def test_missing_jira_env_regression(sample_alert_rule, without_jira_vars,
                                     delete_results):
    from runners import alert_queries_runner
    from runners import alert_suppressions_runner
    from runners import alert_processor
    from runners import alert_dispatcher

    alert_queries_runner.main()
    alert_suppressions_runner.main()
    alert_processor.main()
    alert_dispatcher.main()

    rows = list(db.get_alerts(query_id='test_query_id', suppressed='false'))
    assert len(rows) == 1
    assert rows[0]['TICKET'] is None
예제 #3
0
def test_alert_runners_processor_and_dispatcher(
    sample_alert_rules, update_jira_issue_status_done, delete_results
):

    #
    # queries runner
    #

    from runners import alert_queries_runner

    alert_queries_runner.main()

    # basics
    alert = next(db.get_alerts(query_id='test_1_query_id'))
    assert_dict_is_subset(EXPECTED_TEST_1_OUTPUT, alert)

    query_rule_run_record = list(
        db.fetch('SELECT * FROM data.alert_query_rule_runs ORDER BY query_name')
    )

    assert len(query_rule_run_record) == 7  # 3 from samples + 4 test alert queries

    assert query_rule_run_record[0]['QUERY_NAME'] == 'ACTIVITY_BY_ADMIN_ALERT_QUERY'
    queries_by_admin = 58
    assert query_rule_run_record[0]['NUM_ALERTS_CREATED'] == queries_by_admin

    assert (
        query_rule_run_record[1]['QUERY_NAME']
        == 'SNOWFLAKE_LOGIN_WITHOUT_MFA_ALERT_QUERY'
    )
    assert query_rule_run_record[1]['NUM_ALERTS_CREATED'] == 1

    assert (
        query_rule_run_record[2]['QUERY_NAME']
        == 'SNOWFLAKE_RESOURCE_CREATION_ALERT_QUERY'
    )
    # unclear why this value is non-deterministic in test suite
    resource_creations = query_rule_run_record[2]['NUM_ALERTS_CREATED']
    assert resource_creations >= 40

    assert query_rule_run_record[-4]['QUERY_NAME'] == '_TEST1_ALERT_QUERY'
    assert query_rule_run_record[-4]['NUM_ALERTS_CREATED'] == 1

    assert query_rule_run_record[-3]['QUERY_NAME'] == '_TEST2_ALERT_QUERY'
    assert (
        query_rule_run_record[-3]['NUM_ALERTS_CREATED'] == 1
    )  # second is de-duplicated

    assert query_rule_run_record[-2]['QUERY_NAME'] == '_TEST3_ALERT_QUERY'
    assert query_rule_run_record[-2]['NUM_ALERTS_CREATED'] == 1

    assert query_rule_run_record[-1]['QUERY_NAME'] == '_TEST4_ALERT_QUERY'
    assert query_rule_run_record[-1]['NUM_ALERTS_CREATED'] == 1

    print(query_rule_run_record)

    queries_run_records = list(
        db.fetch('SELECT * FROM data.alert_queries_runs ORDER BY start_time')
    )
    assert len(queries_run_records) == 1
    assert (
        queries_run_records[0]['NUM_ALERTS_CREATED']
        == resource_creations + queries_by_admin + 5
    )
    assert queries_run_records[0]['NUM_ALERTS_UPDATED'] == 0

    # TODO: errors
    # error = query_rule_run_record[3].get('ERROR')
    # assert type(error) is dict
    # assert error['PROGRAMMING_ERROR'] == '100051 (22012): Division by zero'
    # assert 'snowflake.connector.errors.ProgrammingError' in error['EXCEPTION_ONLY']
    # assert 'Traceback (most recent call last)' in error['EXCEPTION']

    #
    # suppressions runner
    #

    from runners import alert_suppressions_runner

    alert_suppressions_runner.main()

    # basics
    alerts = list(db.get_alerts(query_id='suppressed_alert_query_id'))
    assert len(alerts) == 1
    assert alerts[0]['SUPPRESSED'] is True
    assert alerts[0]['TICKET'] is None
    assert alerts[0]['SUPPRESSION_RULE'] == '_TEST2_ALERT_SUPPRESSION'

    suppression_rule_run_records = list(
        db.fetch('SELECT * FROM data.alert_suppression_rule_runs ORDER BY rule_name')
    )
    assert len(suppression_rule_run_records) == 3
    assert suppression_rule_run_records[0]['RUN_ID'] == RUN_ID
    assert (
        suppression_rule_run_records[0]['RULE_NAME']
        == 'SINGLE_FACTOR_EXCEPTIONS_ALERT_SUPPRESSION'
    )
    assert suppression_rule_run_records[0]['NUM_ALERTS_SUPPRESSED'] == 0
    assert suppression_rule_run_records[1]['RUN_ID'] == RUN_ID
    assert suppression_rule_run_records[1]['RULE_NAME'] == '_TEST2_ALERT_SUPPRESSION'
    assert suppression_rule_run_records[1]['NUM_ALERTS_SUPPRESSED'] == 1
    assert suppression_rule_run_records[2]['RUN_ID'] == RUN_ID
    assert (
        suppression_rule_run_records[2]['RULE_NAME']
        == '__SUPPRESS_SAMPLE_ALERTS_ALERT_SUPPRESSION'
    )
    assert (
        suppression_rule_run_records[2]['NUM_ALERTS_SUPPRESSED']
        == resource_creations + queries_by_admin + 1
    )

    suppression_run_records = list(
        db.fetch('SELECT * FROM data.alert_suppressions_runs')
    )
    assert len(suppression_run_records) == 1
    assert_dict_has_subset(
        suppression_run_records[0],
        {
            'RUN_ID': RUN_ID,
            'NUM_ALERTS_SUPPRESSED': resource_creations + queries_by_admin + 2,
            'NUM_ALERTS_PASSED': 3,
        },
    )

    # TODO: errors

    #
    # processor
    #

    from runners import alert_processor

    alert_processor.main()

    # basics
    rows = list(db.get_alerts(actor='Common Test Actor'))
    assert len(rows) == 2
    assert rows[0]['CORRELATION_ID'] is not None
    assert rows[0]['CORRELATION_ID'] != ""
    assert rows[1]['CORRELATION_ID'] is not None
    assert rows[1]['CORRELATION_ID'] != ""
    assert rows[0]['CORRELATION_ID'] == rows[1]['CORRELATION_ID']

    #
    # alert handler
    #
    from runners.handlers import slack

    slack.handle = MagicMock(return_value={'ok': True})
    from runners import alert_dispatcher
    from runners.handlers import jira

    alert_dispatcher.main()

    # jira
    ticket_id = next(db.get_alerts(query_id='test_1_query_id'))['TICKET']
    assert ticket_id is not None
    update_jira_issue_status_done(ticket_id)
    ticket_body = jira.get_ticket_description(ticket_id)
    lines = ticket_body.split('\n')
    assert lines[20] == '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'
    assert {lines[2], lines[23]} == {
        'Query ID: test_1_query_id',
        'Query ID: test_3_query',
    }

    # slack
    alert = next(db.get_alerts(query_id='test_4_query_id'))
    assert alert['HANDLED'] == [{"success": True, "details": SLACK_MOCK_RETURN_VALUE}]
    slack.handle.assert_called_once()