def collect_results(request_info, main_account): security_features = request_info['request_params']['security_features'] regions = request_info['request_params']['regions'] scan_account_id = request_info['request_params']['account_id'] tags = request_info['request_params']['tags'] response = dict({'global': {}}) for region in regions: response[region] = {} for sec_feature in security_features: if sec_feature not in GLOBAL_SECURITY_FEATURES: response[region][sec_feature] = [] else: response['global'][sec_feature] = [] config = Config() for security_feature in security_features: sec_feature_config = config.get_module_config_by_name(security_feature) ddb_table = main_account.resource("dynamodb").Table( sec_feature_config.ddb_table_name) for issue in IssueOperations.get_account_open_issues( ddb_table, scan_account_id): if issue.contains_tags(tags) and ( issue.issue_details.region in regions or security_feature in GLOBAL_SECURITY_FEATURES): issue_region = issue.issue_details.region if issue.issue_details.region else 'global' response[issue_region][security_feature].append({ 'id': issue.issue_id, 'issue_details': issue.issue_details.as_dict() }) return response
def start_scan(account_id, regions, security_features, tags, ids): config = Config() account_name = config.aws.accounts.get(account_id, None) if not account_id: return bad_request(text="account_id is required parameter") if account_name is None: return bad_request(text=f"account '{account_id}' is not defined") valid_security_features = [module.section for module in config.modules] for security_feature in security_features: if security_feature not in valid_security_features: return bad_request( text= f"wrong security feature - '{security_feature}', available choices - {valid_security_features}" ) if not security_features: security_features = valid_security_features all_regions = config.aws.regions for region in regions: if region not in all_regions: return bad_request(text=f"Region '{region} is not supported") # empty list means we want to scan all supported regions if not regions: regions = all_regions if ids is not None and not isinstance(ids, list): return bad_request(text=f"'ids' parameter must be list") if tags is not None and not isinstance(tags, dict): return bad_request(text=f"'tags' parameter must be dict") main_account = Account(region=config.aws.region) api_table = main_account.resource("dynamodb").Table( config.api.ddb_table_name) to_scan = [] for security_feature in security_features: accounts = config.get_module_config_by_name(security_feature).accounts if account_id in accounts: to_scan.append(security_feature) regional_services = set(to_scan) - set(GLOBAL_SECURITY_FEATURES) global_services = set(to_scan).intersection(set(GLOBAL_SECURITY_FEATURES)) total = len(regional_services) * len(regions) + len(global_services) request_params = { "account_id": account_id, "regions": regions, "security_features": to_scan, "tags": tags } request_id = uuid.uuid4().hex DDB.add_request(api_table, request_id, request_params, total) for security_feature in to_scan: topic_name = config.get_module_config_by_name( security_feature).sns_topic_name topic_arn = get_sns_topic_arn(config, topic_name) payload = { "account_id": account_id, "account_name": account_name, "regions": regions, "sns_arn": topic_arn, "request_id": request_id } Sns.publish(topic_arn, payload) response = {'request_id': request_id} return { "statusCode": 200, "body": json.dumps(response, indent=4) if isinstance(response, dict) else response }