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()
def test_get_all_apps(self): """StreamAlertApp - Get All Apps""" expected_apps = { 'box_admin_events', 'duo_admin', 'duo_auth', 'gsuite_access_transparency', 'gsuite_admin', 'gsuite_calendar', 'gsuite_drive', 'gsuite_gplus', 'gsuite_groups', 'gsuite_groups_enterprise', 'gsuite_login', 'gsuite_mobile', 'gsuite_rules', 'gsuite_token', 'gsuite_user_accounts', 'intercom_admin_activity_logs', 'onelogin_events', 'salesforce_console', 'salesforce_login', 'salesforce_loginas', 'salesforce_report', 'salesforce_reportexport', 'slack_access', 'slack_integration', 'aliyun_actiontrail' } assert_equal(expected_apps, set(StreamAlertApp.get_all_apps()))
def _setup_app_new_subparser(cls, 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 ''')) cls._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)
def test_get_app_invalid_type(self): """StreamAlertApp - Get App, Invalid Type""" StreamAlertApp.get_app('bad_app')
def test_get_app(self): """StreamAlertApp - Get App""" assert_equal(StreamAlertApp.get_app('duo_auth'), DuoAuthApp)
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('streamalert_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('streamalert_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']['streamalert_apps'] = apps_config # Add this service to the sources for this app integration # The `streamalert_app` is purposely singular here app_sources = self.config['clusters'][cluster_name][ 'data_sources'].get('streamalert_app', {}) app_sources[func_name] = [app.service()] self.config['clusters'][cluster_name]['data_sources'][ 'streamalert_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
def handler(cls, 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('streamalert_apps') for cluster, cluster_config in config['clusters'].items() } for cluster, info in all_info.items(): print('\nCluster: {}\n'.format(cluster)) if not info: print('\tNo Apps configured\n') continue for name, details in info.items(): 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.items() ] + ['\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('streamalert_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.items(): 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']['streamalert_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