Esempio n. 1
0
def handler(event, context):
    """Main lambda handler use as the entry point

    Args:
        event (dict): Event object that can potentially contain details on what to
            during this invocation. An example of this is the 'invocation_type' key
            that is used as an override to allow for successive invocations (and in
            the future, support for historical invocations)
        context (LambdaContxt): AWS LambdaContext object
    """
    StreamAlertApp.get_app(event['app_type'])(event, context).gather()
Esempio n. 2
0
    def test_get_all_apps(self):
        """StreamAlertApp - Get All Apps"""
        expected_apps = {
            'box_admin_events',
            'duo_admin',
            'duo_auth',
            'gsuite_admin',
            'gsuite_calendar',
            'gsuite_drive',
            'gsuite_gplus',
            'gsuite_groups',
            'gsuite_login',
            'gsuite_mobile',
            'gsuite_rules',
            'gsuite_saml',
            'gsuite_token',
            'onelogin_events',
            'salesforce_console',
            'salesforce_login',
            'salesforce_loginas',
            'salesforce_report',
            'salesforce_reportexport',
            'slack_access',
            'slack_integration',
            'aliyun_actiontrail'
        }

        assert_items_equal(expected_apps, StreamAlertApp.get_all_apps())
Esempio n. 3
0
def _setup_app_new_subparser(subparsers):
    """Add the app new subparser: manage.py app new [options]"""
    app_new_parser = _generate_subparser(
        subparsers,
        'new',
        description=
        'Create a new StreamAlert app to poll logs from various services',
        subcommand=True)

    _set_parser_epilog(app_new_parser,
                       epilog=('''\
            Example:

                manage.py app new \\
                  duo_auth \\
                  --cluster prod \\
                  --name duo_prod_collector \\
                  --schedule-expression 'rate(2 hours)' \\
                  --timeout 60 \\
                  --memory 256
            '''))

    _add_default_app_args(app_new_parser)

    app_types = sorted(StreamAlertApp.get_all_apps())

    # App type options
    app_new_parser.add_argument('type',
                                choices=app_types,
                                metavar='APP_TYPE',
                                help='Type of app being configured: {}'.format(
                                    ', '.join(app_types)))

    # Function schedule expression (rate) arg
    add_schedule_expression_arg(app_new_parser)

    # Function timeout arg
    add_timeout_arg(app_new_parser)

    # Function memory arg
    add_memory_arg(app_new_parser)
Esempio n. 4
0
    def add_app(self, func_name, app_info):
        """Add a configuration for a new streamalert app integration function

        Args:
            app_info (dict): The necessary values needed to begin configuring
                a new app integration

        Returns:
            bool: False if errors occurred, True otherwise
        """
        exists, prompt_for_auth, overwrite = False, True, False
        app = StreamAlertApp.get_app(app_info['type'])

        cluster_name = app_info['cluster']
        app_name = app_info['app_name']

        # Check to see if there is an existing configuration for this app integration
        cluster_config = self.config['clusters'][cluster_name]

        if func_name in cluster_config['modules'].get('stream_alert_apps', {}):
            prompt = (
                'An app with the name \'{}\' is already configured for cluster '
                '\'{}\'. Would you like to update the existing app\'s configuration'
                '?'.format(app_name, cluster_name))

            exists = True

            # Return if the user is not deliberately updating an existing config
            if not continue_prompt(message=prompt):
                return

            prompt = (
                'Would you also like to update the authentication information for '
                'app integration with name \'{}\'?'.format(app_name))

            # If this is true, we shouldn't prompt again to warn about overwriting
            prompt_for_auth = overwrite = continue_prompt(message=prompt)

        if prompt_for_auth and not save_app_auth_info(app, app_info, func_name,
                                                      overwrite):
            return False

        apps_config = cluster_config['modules'].get('stream_alert_apps', {})
        if not exists:
            # Save a default app settings to the config for new apps
            new_app_config = {
                'app_name': app_info['app_name'],
                'concurrency_limit': 2,
                'log_level': 'info',
                'log_retention_days': 14,
                'memory': app_info['memory'],
                'metric_alarms': {
                    'errors': {
                        'enabled': True,
                        'evaluation_periods': 1,
                        'period_secs': 120
                    }
                },
                'schedule_expression': app_info['schedule_expression'],
                'timeout': app_info['timeout'],
                'type': app_info['type']
            }
            apps_config[func_name] = new_app_config
        else:

            # Allow for updating certain attributes for the app without overwriting
            # current parts of the configuration
            updated_app_config = {
                'memory': app_info['memory'],
                'schedule_expression': app_info['schedule_expression'],
                'timeout': app_info['timeout']
            }
            apps_config[func_name].update(updated_app_config)

        cluster_config['modules']['stream_alert_apps'] = apps_config

        # Add this service to the sources for this app integration
        # The `stream_alert_app` is purposely singular here
        app_sources = self.config['sources'].get('stream_alert_app', {})
        app_sources[func_name] = {'logs': [app.service()]}
        self.config['sources']['stream_alert_app'] = app_sources

        LOGGER.info(
            'Successfully added \'%s\' app integration to \'conf/clusters/%s.json\' '
            'for service \'%s\'.', app_info['app_name'], app_info['cluster'],
            app_info['type'])

        self.write()

        return True
Esempio n. 5
0
def _app_handler(options):
    """Perform app related functions

    Args:
        options (argparser): Contains all of the necessary info for configuring
            a new app integration or updating an existing one
    """
    if not options:
        return

    # Convert the options to a dict
    app_info = vars(options)

    # Add the region and prefix for this StreamAlert instance to the app info
    app_info['region'] = str(CONFIG['global']['account']['region'])
    app_info['prefix'] = str(CONFIG['global']['account']['prefix'])

    # Function name follows the format: '<prefix>_<cluster>_<service>_<app_name>_app
    func_parts = ['prefix', 'cluster', 'type', 'app_name']

    # Create a new app integration function
    if options.subcommand == 'new':
        app_info['function_name'] = '_'.join([app_info.get(value)
                                              for value in func_parts] + ['app'])

        CONFIG.add_app(app_info)
        return

    # Update the auth information for an existing app integration function
    if options.subcommand == 'update-auth':
        cluster_config = CONFIG['clusters'][app_info['cluster']]
        if not app_info['app_name'] in cluster_config['modules'].get('stream_alert_apps', {}):
            LOGGER_CLI.error('App integration with name \'%s\' does not exist for cluster \'%s\'',
                             app_info['app_name'], app_info['cluster'])
            return

        # Get the type for this app integration from the current
        # config so we can update it properly
        app_info['type'] = cluster_config['modules']['stream_alert_apps'] \
                                         [app_info['app_name']]['type']

        app_info['function_name'] = '_'.join([app_info.get(value)
                                              for value in func_parts] + ['app'])

        app = StreamAlertApp.get_app(app_info['type'])

        if not save_app_auth_info(app, app_info, True):
            return

        return

    # List all of the available app integrations, broken down by cluster
    if options.subcommand == 'list':
        all_info = {
            cluster: cluster_config['modules'].get('stream_alert_apps')
            for cluster, cluster_config in CONFIG['clusters'].iteritems()
        }

        for cluster, info in all_info.iteritems():
            print '\nCluster: {}\n'.format(cluster)
            if not info:
                print '\tNo Apps configured\n'
                continue

            for name, details in info.iteritems():
                print '\tName: {}'.format(name)
                print '\n'.join([
                    '\t\t{key}:{padding_char:<{padding_count}}{value}'.format(
                        key=key_name,
                        padding_char=' ',
                        padding_count=30 - (len(key_name)),
                        value=value) for key_name, value in details.iteritems()
                ] + ['\n'])
Esempio n. 6
0
 def test_get_app_invalid_type(self):
     """StreamAlertApp - Get App, Invalid Type"""
     StreamAlertApp.get_app('bad_app')
Esempio n. 7
0
 def test_get_app(self):
     """StreamAlertApp - Get App"""
     assert_equal(StreamAlertApp.get_app('duo_auth'), DuoAuthApp)
Esempio n. 8
0
def app_handler(options, config):
    """Perform app related functions

    Args:
        options (argparse.Namespace): Parsed arguments with info to configure a new app
            or update an existing one
        config (CLIConfig): Loaded StreamAlert config

    Returns:
        bool: False if errors occurred, True otherwise
    """
    if not options:
        return False

    # List all of the available app integrations, broken down by cluster
    if options.subcommand == 'list':
        all_info = {
            cluster: cluster_config['modules'].get('stream_alert_apps')
            for cluster, cluster_config in config['clusters'].iteritems()
        }

        for cluster, info in all_info.iteritems():
            print '\nCluster: {}\n'.format(cluster)
            if not info:
                print '\tNo Apps configured\n'
                continue

            for name, details in info.iteritems():
                print '\tName: {}'.format(name)
                print '\n'.join([
                    '\t\t{key}:{padding_char:<{padding_count}}{value}'.format(
                        key=key_name,
                        padding_char=' ',
                        padding_count=30 - (len(key_name)),
                        value=value)
                    for key_name, value in details.iteritems()
                ] + ['\n'])
        return True

    # Convert the options to a dict
    app_info = vars(options)

    # Add the region and prefix for this StreamAlert instance to the app info
    app_info['region'] = str(config['global']['account']['region'])
    app_info['prefix'] = str(config['global']['account']['prefix'])

    # Create a new app integration function
    if options.subcommand == 'new':
        function_name = '_'.join([
            app_info['prefix'], app_info['cluster'], app_info['type'],
            app_info['app_name'], 'app'
        ])

        return config.add_app(function_name, app_info)

    # Update the auth information for an existing app integration function
    if options.subcommand == 'update-auth':
        cluster_config = config['clusters'][app_info['cluster']]
        apps = cluster_config['modules'].get('stream_alert_apps', {})
        if not apps:
            LOGGER.error('No apps configured for cluster \'%s\'',
                         app_info['cluster'])
            return False

        # Find the appropriate function config for this app
        func_name = None
        for function_name, app_config in apps.iteritems():
            if app_config.get('app_name') == app_info['app_name']:
                func_name = function_name
                break

        if not func_name:
            LOGGER.error(
                'App with name \'%s\' does not exist for cluster \'%s\'',
                app_info['app_name'], app_info['cluster'])
            return False

        # Get the type for this app integration from the current
        # config so we can update it properly
        app_info['type'] = cluster_config['modules']['stream_alert_apps'][
            func_name]['type']

        app = StreamAlertApp.get_app(app_info['type'])

        if not save_app_auth_info(app, app_info, func_name, True):
            return False

        return True